码迷,mamicode.com
首页 > 其他好文 > 详细

drf之jwt傻瓜式启动说明书

时间:2020-07-16 00:22:47      阅读:65      评论:0      收藏:0      [点我收藏+]

标签:header   str   int   mis   src   信息   使用   set   数据库   

DRF之jwt使用说明书

jwt介绍

JsonWebToken

如何获取token

先创建一张用户表,要想使用jwt,必须使用django自带的用户表

技术图片

技术图片

  • 在models.py中写一个用户类,导入、继承AbstractUser

  • 在Terminal中做数据库迁移,createsuperuser创建超级用户

  • 在路由中导入jwt的模块

    # urls.py
    from django.urls import path, include,re_path
    from rest_framework_jwt.views import obtain_jwt_token
    from api import views
    
    urlpatterns = [
        path(‘loginView/‘, views.Login.as_view()),
        re_path(r"^login/", obtain_jwt_token)
        # login触发jwt的视图函数
    ]
    
  • 向login发送post请求,请求体中加上username,password(这取决于用户表中的字段名),只需要且只能用这两个来认证

  • 得到响应,响应中就是token

    技术图片

这里就得到了token,这个token有默认的过期时间,把它放在请求头可以用来做登陆认证

自定义认证

前端完成登陆,获取了token,放在请求头中发送给后端,后端接收并进行验证

如果使用jwt内置的认证方法,默认会把你header里token分开为两段,第一段是 JWT 第二段是token,jwt会拿第二段去认证

注:登录接口需要做 认证 + 权限 两个局部禁用

# auth.py
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
from rest_framework_jwt.authentication import jwt_decode_handler
from rest_framework import exceptions

class MyToken(BaseJSONWebTokenAuthentication):
    # 继承jwt的方法,重写authenticate
    def authenticate(self, request):
        jwt_value = str(request.META.get(‘HTTP_AUTHORIZATION‘))
        # 从请求头中取出token:http会自动把前端的authorization变成大写,加上HTTP_前缀
        try:
            payload = jwt_decode_handler(jwt_value)
            # 使用继承的类中的方法取token中的payload,验证
            print(payload)
        except Exception:
            raise exceptions.AuthenticationFailed("认证失败")
        user = self.authenticate_credentials(payload)
        return user, None
    # 认证成功,返回用户对象,这时就可以在视图中任意位置取payload中给的信息了
# views.py
from rest_framework.views import APIView
from rest_framework.response import Response
from utils.auth import MyToken

class Login(APIView):
    authentication_classes = [MyToken,]
    # 局部使用,配置认证类。如果要全局使用,去setting中配置
    def get(self,request):
        return Response("Login")

使用内置的认证

内置的jwt前端使用格式是这样

技术图片

访问需要登陆认证后才能访问的url时,在请求头(Header)中添加 Authorization:JWT <your_token> (Authorization 为 name,JWT <your_token> 为 value)

后端使用jwt内置的认证方式,仅需导入两个模块配置一下就可以了

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
# 认证模块
from rest_framework.permissions import IsAuthenticated
# 权限模块
from utils.auth import MyToken

class Login(APIView):
    authentication_classes = [JSONWebTokenAuthentication,]
    permission_classes = [IsAuthenticated]
    # 配置认证和权限
    def get(self,request):
        return Response("Login")

注意,使用内置的认证方法,必须认证和权限一起使用才能有效,只使用一个认证不用权限,也可以访问到接口

控制返回的数据格式

控制登陆接口返回的数据格式,让obtain_jwt_token不止返回一个“token”,重写整个登陆接口,或使用原有的登陆接口,改一些配置

第一种方法,改配置

在jwt的配置文件中有个属性

‘JWT_RESPONSE_PAYLOAD_HANDLER‘:‘rest_framework_jwt.utils.jwt_response_payload_handler‘,

控制返回数据的格式,我们只要重写jwt_response_payload_handler的返回值,配置进去就可以控制返回的数据格式了

# setting.py 或者任意别的能先于jwt执行到的地方
from api.utils
JWT_AUTH = {
	‘JWT_RESPONSE_PAYLOAD_HANDLER‘:‘api.utils.my_jwt_response_payload_handler‘
}
# utils.py
def my_jwt_response_payload_handler(token,user=None,request=None):
    return {
        ‘token‘:token,
        ‘status‘:200,
        ‘msg‘:‘登陆成功‘
    }

技术图片

自定义基于jwt的认证类

两种写法

# auth.py
# 第一种,基于BaseAuthentication
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
# from rest_framework_jwt.authentication import jwt_decode_handler
from rest_framework_jwt.utils import jwt_decode_handler # 跟上面是一个
import jwt

from api import models
class MyJwtAuthentication(BaseAuthentication):
    def authenticate(self, request):
        jwt_value=request.META.get(‘HTTP_AUTHORIZATION‘)
        if jwt_value:
            try:
            # jwt提供了通过三段token,取出payload的方法,并且有校验功能
                payload=jwt_decode_handler(jwt_value)
            except jwt.ExpiredSignature:
                raise AuthenticationFailed(‘签名过期‘)
            except jwt.InvalidTokenError:
                raise AuthenticationFailed(‘用户非法‘)
            except Exception as e:
                # 所有异常都会走到这
                raise AuthenticationFailed(str(e))
            # 因为payload就是用户信息的字典
            print(payload)
            # return payload, jwt_value
            # 需要得到user对象,
            # 第一种,去数据库查
            # user=models.User.objects.get(pk=payload.get(‘user_id‘))
            # 第二种不查库
            user=models.User(id=payload.get(‘user_id‘),username=payload.get(‘username‘))
            return user,jwt_value
        # 没有值,直接抛异常
        raise AuthenticationFailed(‘您没有携带认证信息‘)

第二种

# 基于BaseJSONWebTokenAuthentication
from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication
class MyJwtAuthentication(BaseJSONWebTokenAuthentication):
    def authenticate(self, request):
        jwt_value=request.META.get(‘HTTP_AUTHORIZATION‘)
        if jwt_value:
            try:
            #jwt提供了通过三段token,取出payload的方法,并且有校验功能
                payload=jwt_decode_handler(jwt_value)
            except jwt.ExpiredSignature:
                raise AuthenticationFailed(‘签名过期‘)
            except jwt.InvalidTokenError:
                raise AuthenticationFailed(‘用户非法‘)
            except Exception as e:
                # 所有异常都会走到这
                raise AuthenticationFailed(str(e))
            user=self.authenticate_credentials(payload)
            return user,jwt_value
        # 没有值,直接抛异常
        raise AuthenticationFailed(‘您没有携带认证信息‘)

在视图中使用authentication_classes = [MyJwtAuthentication,]导入使用

drf之jwt傻瓜式启动说明书

标签:header   str   int   mis   src   信息   使用   set   数据库   

原文地址:https://www.cnblogs.com/telecasterfanclub/p/13308412.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!