jwt+djangorestframework

僤鯓⒐⒋嵵緔 提交于 2019-12-22 02:08:46

创建一个名为API的Django工程目录和名为Blog_RestApi的app

API----->urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/',include('Blog_RestApi.urls'))
]

API----->Blog_RestApi----->urls.py

from django.urls import path, include
from Blog_RestApi import views


urlpatterns=[
  
    path('sublogin/', views.SupLoginView.as_view()),
    path('suborder/', views.SubOrderView.as_view()),

]

生成jwt的token模块
Blog_RestApi---->utils---->jwt_create_token.py

import datetime
import jwt

from django.conf import settings


def create_token(payload, timeout=1):
    # 盐值
    salt = settings.SECRET_KEY
    # 固定头部格式,也可以自己改
    headers = {
        'type': 'jwt',
        'alg': 'HS256'
    }
    # 设置payload内容,目前只加一个超时时间,其他的自定义
    payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
    # 生成token
    token = jwt.encode(payload=payload, key=salt, headers=headers).decode("utf-8")
    return token

验证token模块
Blog_RestApi---->extensions---->auth.py

import jwt
from jwt import exceptions
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.authentication import BaseAuthentication
from django.conf import settings


class JWTQueryParamsAuthentication(BaseAuthentication):

    def authenticate(self, request):
        # 获取token并判断token的合法性
        token = request.query_params.get('token')
        # 盐值
        salt = settings.SECRET_KEY
        """
        1。切割成三部分
        2。取出并解密第二部分payload:判断token是否超时
        3。验证第三部分:加盐并验证token合法性
        """
        try:
            # 从token中获取payload并校验合法性
            # jwt.decode(token,salt,True):内部集成了以上三个步骤
            payload = jwt.decode(token, salt, True)
        except  exceptions.ExpiredSignatureError:
            raise AuthenticationFailed({'code': 403, 'error': "token已经失效"})
        except  jwt.DecodeError:
            raise AuthenticationFailed({'code': 403, 'error': "token认证失效"})
        except  jwt.InvalidTokenError:
            raise AuthenticationFailed({'code': 403, 'error': '非法token'})

        """ 
            
            def authenticate(self, request):
            
            #验证请求并返回(用户,令牌)的二元组
            #Authenticate the request and return a two-tuple of (user, token).
        
            raise NotImplementedError(".authenticate() must be overridden.")
        """
        ##request.user=payload信息,    request.token=token信息
        return (payload, token)

数据模型
Blog_RestApi---->models.py

class  User(models.Model):
    username=models.CharField(max_length=32)
    passwd=models.CharField(max_length=64)
    ##允许这个字符串为空
    token=models.CharField(max_length=64,blank=True)

视图
Blog_RestApi---->views.py

from Blog_RestApi.models import  User
from rest_framework.views import APIView
from rest_framework.response import Response
from Blog_RestApi.utils.jwt_create_token import create_token

##用户登陆并生成token
class SupLoginView(APIView):
	#当将token验证集成到settings的时候,可通过[]避免token认证
    #authentication_classes = []
    def post(self, request, *args, **kwargs):
        # request.data返回请求正文的解析内容
        user = request.data.get('username')
        pwd = request.data.get('password')
        user_object = User.objects.filter(username=user, passwd=pwd).first()
        ##如果用户名和密码不正确
        if not user_object:
            return Response({'code': 403, 'error': '用户名或密码错误'})
        # 生成token:
        token = create_token({'id': user_object.id, 'name': user_object.username})
        # 每post一次随机字符串token会变,数据库也会更新token
        user_object.save()
        # 返回给用户token
        return Response({'code': 200, 'data': token})



from Blog_RestApi.extensions.auth import JWTQueryParamsAuthentication

##token认证
class SubOrderView(APIView):
    ##认证,只有通过token认证后才能执行下边试图函数
    ##也可以集成到settings中,让所有视图函数(除了login试图函数)都需要token认证
    authentication_classes = [JWTQueryParamsAuthentication]

    def get(self, request, *args, **kwargs):
        #print(request.user)
        return Response('验证成功')

将token验证集成到settings配置中

1.查看父类APIView中的settings

class APIView(View):

    # The following policies may be set at either globally, or per-view.
    renderer_classes = api_settings.DEFAULT_RENDERER_CLASSES
    parser_classes = api_settings.DEFAULT_PARSER_CLASSES
    ##默认的认证配置
    authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
    throttle_classes = api_settings.DEFAULT_THROTTLE_CLASSES
    permission_classes = api_settings.DEFAULT_PERMISSION_CLASSES
    content_negotiation_class = api_settings.DEFAULT_CONTENT_NEGOTIATION_CLASS
    metadata_class = api_settings.DEFAULT_METADATA_CLASS
    versioning_class = api_settings.DEFAULT_VERSIONING_CLASS

    # Allow dependency injection of other settings to make testing easier.
    settings = api_settings

2.将token验证集成到settings配置中,

REST_FARMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES': ['Blog_RestApi.extensions.auth.JWTQueryParamsAuthentication']
}

验证:

登陆生成token
在这里插入图片描述
正确token
在这里插入图片描述
token超时后
在这里插入图片描述
错误的token
在这里插入图片描述

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!