88

我已经阅读了 Django Rest Framework Guides 并完成了所有教程。一切似乎都有意义,并且按应有的方式工作。我得到了基本和会话身份验证的工作描述。

django rest 框架 - api 指南

但是,我在文档的令牌身份验证部分苦苦挣扎,它有点缺乏或没有像教程那样深入。

django-rest-framework - 令牌认证

它说我需要为用户创建令牌,但确实说明了 models.py 的位置?

有人可以为初学者更好地解释文档的令牌身份验证部分吗?

4

7 回答 7

94

@ian-clelland has already provided the correct answer. There are just a few tiny pieces that wasn't mentioned in his post, so I am going to document the full procedures (I am using Django 1.8.5 and DRF 3.2.4):

  1. Do the following things BEFORE you create the superuser. Otherwise, the superuser does not get his/her token created.

  2. Go to settings.py and add the following:

    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. Add the following code in 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)
    

    Alternatively, if you want to be more explicit, create a file named signals.py under myapp project. Put the code above in it, then in __init__.py, write import signals

  4. Open up a console window, navigate to your project dir, and enter the following command:

    python manage.py migrate
    python manage.py makemigrations
    

    Take a look in your database, a table named authtoken_token should be created with the following fields: key (this is the token value), created (the datetime it was created), user_id (a foreign key that references the auth_user table's id column)

  5. create a superuser with python manage.py createsuperuser. Now, take a look at the authtoken_token table in your DB with select * from authtoken_token;, you should see a new entry has been added.

  6. Using curl or a much simpler alternative httpie to test access to your api, I am using httpie:

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

    That's it. From now on, for any API access, you need to include the following value in the HTTP header (pay attention to the whitespaces):

    Authorization: Token your_token_value
    
  7. (Optional) DRF also provides the ability to return a user's token if you supply the username and password. All you have to do is to include the following in urls.py:

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

    Using httpie to verify:

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

    In the return body, you should see this:

    {
        "token": "blah_blah_blah"
    }
    

That's it!

于 2015-10-27T03:13:54.090 回答
75

不,不在你的 models.py 中——在模型方面,你需要做的就是rest_framework.authtoken在你的INSTALLED_APPS. 这将提供一个外键给用户的 Token 模型。

您需要做的是决定何时以及如何创建这些令牌对象。在您的应用程序中,是否每个用户都会自动获得令牌?还是只有某些授权用户?还是只有当他们特别要求时?

如果每个用户都应该有一个令牌,那么在您链接到的页面上会有一段代码向您展示如何设置一个信号来自动创建它们:

@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)

创建(并保存)令牌后,它将可用于身份验证。

于 2013-02-12T17:30:55.267 回答
19

在 Django 1.8.2 和 rest framework 3.3.2 上,以上所有内容不足以启用基于令牌的身份验证。

虽然 REST_FRAMEWORK 设置在 django 设置文件中指定,但基于函数的视图需要 @api_view 装饰器:

from rest_framework.decorators import api_view

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

否则根本不执行令牌认证

于 2016-01-24T00:12:29.090 回答
15

只是为了增加我的两分钱,如果您有一个处理用户创建(和激活)的自定义用户管理器,您也可以像这样执行此任务:

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 shell 并为您的数据库中的所有用户创建令牌。

>>> 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)

希望有帮助。

于 2014-01-21T01:32:35.307 回答
10

有一种更简洁的方式来获取用户令牌。

只需运行 manage.py shell

接着

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 中找到一条记录

于 2016-03-02T05:53:51.877 回答
7

除了这里的优秀答案,我想提一个更好的令牌认证方法:JSON Web Token Authentication。http://getblimp.github.io/django-rest-framework-jwt/提供的实现非常容易使用。

此答案中更详细地解释了这些好处。

于 2016-09-10T04:38:29.170 回答
1

JSON Web Token Authentication 是比 Token Authentication 更好的选择。该项目已使用 Django ( http://getblimp.github.io/django-rest-framework-jwt/ ) 实现了 JWT Auth,但目前该项目未维护。

对于替代方案,您可以遵循: https ://github.com/davesque/django-rest-framework-simplejwt

于 2019-09-19T10:22:32.383 回答