drf使用jwt做验证

drf使用jwt做验证

之前做网站是用django自带的登录,在'django.contrib.auth.urls下有登录、注销等等Django已经提供好的。

urlpatterns = [
    url(r'^login/$', views.LoginView.as_view(), name='login'),
    url(r'^logout/$', views.LogoutView.as_view(), name='logout'),

    url(r'^password_change/$', views.PasswordChangeView.as_view(), name='password_change'),
    url(r'^password_change/done/$', views.PasswordChangeDoneView.as_view(), name='password_change_done'),

    url(r'^password_reset/$', views.PasswordResetView.as_view(), name='password_reset'),
    url(r'^password_reset/done/$', views.PasswordResetDoneView.as_view(), name='password_reset_done'),
    url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
        views.PasswordResetConfirmView.as_view(), name='password_reset_confirm'),
    url(r'^reset/done/$', views.PasswordResetCompleteView.as_view(), name='password_reset_complete'),
]

但现在做前后端分离的接口的登录就需要自己来写了。

session与JSON Web Token区别

在做学校三级项目时我们是将用户通过接口登录后,生成sessionid存到redis里 userid:sessionid。然后sessionid返回给用户,用户在之后进行需要验证身份的操作时带上sessionid和userid,后端验证这个sessionid是否与redis中的sessionid是否相同。

Token和session其实都是为了身份验证,session需要我们进行存贮,用于日后比对,而Token不用。

Token是使用算法的方式进行验证,就不需要进行往数据库里存了。

drf自带Token与JSON Web Token区别

drf 自带的token也是新建一张Token表,里面存了用户和随机值Token的对应关系,和三级项目数据库里存sessionid没什么区别,只不过drf的token要放在请求header里,普通接口的sessionid放在get或post请求中。

使用 django-rest-framework-jwt

django有现成的jwt轮子 django-rest-framework-jwt,可以拿来使用。

pip install djangorestframework-jwt

安装后设置权限认证

设置PERMISSION_CLASSES和AUTHENTICATION_CLASSES

可以在setting中全局设置进行

REST_FRAMEWORK = {
    # 权限认证
    'DEFAULT_PERMISSION_CLASSES': (
        'rest_framework.permissions.IsAuthenticated',
    ),
    # 身份验证
    'DEFAULT_AUTHENTICATION_CLASSES': (
        'rest_framework_jwt.authentication.JSONWebTokenAuthentication',
        'rest_framework.authentication.SessionAuthentication',
        'rest_framework.authentication.BasicAuthentication',
    ),
}

也可以在指定的ViewSet下设置权限,比如对商品信息做权限认证,需登录后才能获得信息。

   class GoodsViewSet(viewsets.ReadOnlyModelViewSet):
       """
       商品列表
       商品详情
       """
       queryset = Goods.objects.all()
       # 序列化
       serializer_class = GoodsSerializer
       # 分页
       pagination_class = StandardResultsSetPagination
       # 过滤
       filter_backends = (filters.DjangoFilterBackend, SearchFilter, OrderingFilter)
       filterset_class = GoodsFilter
       ordering_fields = ('add_time', )
       search_fields = ('name', 'goods_desc')
       #Token认证
       permission_classes = (IsAuthenticated,)

添加url

from rest_framework_jwt.views import obtain_jwt_token
#...

urlpatterns = [
    '',
    # ...

    url(r'^api-token-auth/', obtain_jwt_token),
]

此时直接访问http://127.0.0.1:8000/goods/返回

{
  "detail": "身份认证信息未提供。"
}

获取token

$ curl -X POST -H "Content-Type: application/json" -d '{"username":"admin","password":"password123"}' http://localhost:8000/api-token-auth/

返回

{"token":"eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImhlaGVjYXQiLCJleHAiOjE1MzIxNTIwNzUsImVtYWlsIjoicXdlQHF3ZS5xcSJ9.3zLJFaMjY8q3VC3aUdy5N79sbWelse0sSfp5yKOaNUs"}

访问需权限的url

$ curl -H "Authorization: JWT eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ1c2VyX2lkIjoxLCJ1c2VybmFtZSI6ImhlaGVjYXQiLCJleHAiOjE1MzIxNTIwNzUsImVtYWlsIjoicXdlQHF3ZS5xcSJ9.3zLJFaMjY8q3VC3aUdy5N79sbWelse0sSfp5yKOaNUs" http://localhost:8000/goods/

修改登录验证

登录默认 使用django的ModelBackend,对用户名和密码进行验证。但我们平时登录网站时除了用户名也可以用邮箱或手机进行登录,这就需要我们自己扩展backend。

AUTHENTICATION_BACKENDS = {
    'django.contrib.auth.backends.ModelBackend',
}

新建backend

users.views中新建backend,对用户名或手机进行验证

from django.contrib.auth.backends import ModelBackend
from django.contrib.auth import get_user_model

from django.db.models import Q

User = get_user_model()


class CustomBackend(ModelBackend):
    def authenticate(self, request, username=None, password=None, **kwargs):
        try:
            user = User.objects.get(Q(username=username) | Q(mobile=username))
            if user.check_password(password):
                return user
        except Exception as e:
            return None

设置认证backend

settings 中添加

AUTHENTICATION_BACKENDS = {
    'users.views.CustomBackend'
}

猜你喜欢

转载自www.cnblogs.com/hehecat/p/9346700.html
今日推荐