Аутентифікація маркера Django Rest Framework


78

Я прочитав Посібники з Django Rest Framework і провів усі підручники. Здавалося, все має сенс і працює так, як слід. Я отримав базову аутентифікацію та аутентифікацію сеансу, як описано. http://django-rest-framework.org/api-guide

Однак я боюся з частиною документації щодо автентифікації маркера, її трохи не вистачає або не вдається настільки глибоко, як навчальні посібники.
http://django-rest-framework.org/api-guide/authentication/#tokenauthentication

Там сказано, що мені потрібно створити маркери для користувачів, але вказано, де, у models.py?

Моє запитання:

Хтось може пояснити частину документації щодо автентифікації маркера трохи краще для першого таймера?

Відповіді:


72

Ні, не у вашому models.py - з боку моделей все, що вам потрібно зробити, це включити відповідний додаток ( rest_framework.authtoken) до свого INSTALLED_APPS. Це забезпечить модель токена, яка має зовнішній ключ для користувача.

Що вам потрібно зробити, це вирішити, коли і як слід створювати ці маркери. Чи кожен користувач автоматично отримує маркер у вашому додатку? Або лише певні авторизовані користувачі? Або лише тоді, коли вони спеціально просять такого?

Якщо у кожного користувача завжди повинен бути маркер, на сторінці, на яку ви посилаєтесь, є фрагмент коду, який показує, як налаштувати сигнал для їх автоматичного створення:

@receiver(post_save, sender=User)
def create_auth_token(sender, instance=None, created=False, **kwargs):
    if created:
        Token.objects.create(user=instance)

(помістіть це у файл models.py, де завгодно, і він буде зареєстрований при запуску потоку Django)

Якщо маркери слід створювати лише в певний час, тоді у коді перегляду вам потрібно створити та зберегти маркер у відповідний час:

# View Pseudocode
from rest_framework.authtoken.models import Token

def token_request(request):
    if user_requested_token() and token_request_is_warranted():
        new_token = Token.objects.create(user=request.user)

Після створення (та збереження) маркера він буде використаний для автентифікації.


що означає post_save ?
244боя,

2
@ 244boy Він встановлюється create_auth_tokenяк обробник сигналу, щоб кожен раз, коли Userзберігається a (отже post_save), отримував виклик create_auth_token. Сигнали - це внутрішній механізм обробки подій життєвого циклу django.
Джим К.

86

@ ian-clelland вже дав правильну відповідь. Є лише кілька крихітних частин, про які не згадувалось у його дописі, тому я збираюся задокументувати всі процедури (я використовую Django 1.8.5 та DRF 3.2.4):

  1. Виконайте наступні дії ПЕРЕД тим, як створити суперкористувача. В іншому випадку суперкористувач не створює свій маркер.

  2. Перейдіть до settings.py і додайте наступне:

    INSTALLED_APPS = (
        'rest_framework',
        'rest_framework.authtoken',
        'myapp',
    )
    
    REST_FRAMEWORK = {
        'DEFAULT_PERMISSION_CLASSES': (
            'rest_framework.permissions.IsAuthenticated',
        ),
        'DEFAULT_AUTHENTICATION_CLASSES': (
            'rest_framework.authentication.TokenAuthentication',
        )
    }
    
  3. Додайте наступний код у myapp 's models.py :

    from django.db.models.signals import post_save
    from django.dispatch import receiver
    from rest_framework.authtoken.models import Token
    from django.conf import settings
    
    # This code is triggered whenever a new user has been created and saved to the database
    @receiver(post_save, sender=settings.AUTH_USER_MODEL)
    def create_auth_token(sender, instance=None, created=False, **kwargs):
        if created:
            Token.objects.create(user=instance)
    

    З іншого боку , якщо ви хочете бути більш явним, створити файл з ім'ям signals.py під MYAPP проекту. Помістіть в нього код вище, потім у __init__.py напишітьimport signals

  4. Відкрийте вікно консолі, перейдіть до каталогу проекту та введіть таку команду:

    python manage.py migrate
    python manage.py makemigrations
    

    Погляньте у свою базу даних, слід створити таблицю з іменем authtoken_token з наступними полями: key (це значення маркера), created (дата та час його створення), user_id (зовнішній ключ, який посилається на стовпець id таблиці auth_user)

  5. створити суперкористувача за допомогою python manage.py createsuperuser. Тепер, погляньте на таблицю authtoken_token у вашій БД за допомогою select * from authtoken_token;, ви побачите, що додано новий запис.

  6. Використовуючи curlчи набагато простіший альтернативний httpie для перевірки доступу до вашого API, я використовую httpie:

    http GET 127.0.0.1:8000/whatever 'Authorization: Token your_token_value'
    

    Це воно. Відтепер для будь-якого доступу до API потрібно включати таке значення в заголовок HTTP ( зверніть увагу на пробіли ):

    Authorization: Token your_token_value
    
  7. (Необов’язково) DRF також надає можливість повернути маркер користувача, якщо ви надаєте ім’я користувача та пароль. Все, що вам потрібно зробити, це включити в urls.py наступне :

    from rest_framework.authtoken import views
    
    urlpatterns = [
        ...
        url(r'^api-token-auth/', views.obtain_auth_token),
    ]
    

    Використання httpie для перевірки:

    http POST 127.0.0.1:8000/api-token-auth/ username='admin' password='whatever'
    

    У тілі повернення ви повинні побачити таке:

    {
        "token": "blah_blah_blah"
    }
    

Це воно!


Дякую за детальний коментар. де збігається маркер? Чи можемо ми щось редагувати?
Від'я

1
@rrmo Токени зберігаються в таблиці бази даних з назвою auth_token (або щось подібне, я не можу запам'ятати точну назву. У таблиці є лише три стовпці, первинний ключ, маркер та зовнішній ключ для моделі користувача). Щоразу, коли надходить запит на автентифікацію, я думаю, що таблиця бази даних отримується для порівняння вхідного маркера із збереженими.
Ченг

@Cheng Що стосується точки # 3: Введення коду в signals.py і додавання import signalsв __init__.pyпідвищеннях django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yetв Django 1.9.
narendra-choudhary

Але як ви отримуєте маркер, наприклад, з мобільного додатка, ви генеруєте маркер за допомогою імені користувача та пароля (наприклад, створюєте маркер base64) і надсилаєте його у запиті?
Jesus Almaral - Hackaprende

@JesusAlmaral Токен створюється на стороні сервера, а не на стороні клієнта. Після того, як користувач заповнить реєстраційну інформацію та надішле її на сервер для створення облікового запису, разом з обліковим записом створюється маркер. Після створення маркера ви можете надіслати його значення клієнтській стороні.
Ченг

18

На Django 1.8.2 та rest framework 3.3.2 слідування усьому вищезазначеному було недостатньо для того, щоб увімкнути автентифікацію на основі маркерів.

Хоча параметр REST_FRAMEWORK вказаний у файлі налаштувань django, перегляди на основі функцій вимагають @api_view decorator:

from rest_framework.decorators import api_view

@api_view(['POST','GET'])
def my_view(request):
    if request.user.is_authenticated():
       ...

В іншому випадку аутентифікація маркера не виконується взагалі


2
Незважаючи на кілька прихильностей, ця відповідь додає дуже корисний момент: без декоратора @api_view подання не використовуватимуть маркер auth. Можливо, його можна було б додати до обраної відповіді.
Паоло Стефан

Два з половиною роки потому ... ДЯКУЮ
zobbo

14

Просто, щоб додати до цього мої два центи, якщо у вас є спеціальний менеджер користувачів, який займається створенням користувача (і активацією), ви також можете виконати це завдання таким чином:

from rest_framework.authtoken.models import Token
# Other imports

class UserManager(BaseUserManager):

    def create_user(self, **kwargs):
        """
        This is your custom method for creating user instances. 
        IMHO, if you're going to do this, you might as well use a signal.

        """
        # user = self.model(**kwargs) ...
        Token.objects.create(user=user)

    #You may also choose to handle this upon user activation. 
    #Again, a signal works as well here.

    def activate_user(**kwargs):
        # user = ...
        Token.objects.create(user=user)

Якщо у вас вже створені користувачі, ви можете зайти в оболонку python у своєму терміналі та створити маркери для всіх користувачів у вашій базі даних.

>>> from django.contrib.auth.models import User
>>> from rest_framework.authtoken.models import Token 
>>> for user in User.objects.all():
>>> ...    Token.objects.create(user=user)

Сподіваюся, що це допомагає.


10

Існує більш чистий спосіб отримати токен користувача.

просто запустіть оболонку manage.py

і потім

from rest_framework.authtoken.models import Token
from django.contrib.auth.models import User
u = User.objects.get(username='admin')
token = Token.objects.create(user=u)
print token.key

тоді запис слід знайти в таблиці DB_Schema.authtoken_token



1

JSON Web Token Authentication є кращою альтернативою, ніж Token Authentication. Цей проект реалізував JWT Auth з Django ( http://getblimp.github.io/django-rest-framework-jwt/ ), але наразі проект не підтримується.

Для альтернативних варіантів ви можете перейти за посиланням: https://github.com/davesque/django-rest-framework-simplejwt

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.