Аутентифікація маркера 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.