• drf之jwt傻瓜式启动说明书


    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,]导入使用

  • 相关阅读:
    java基础(七)面向对象(二)
    java基础 (六)面向对象(一)
    java基础(五)
    java基础(四)
    sqlloader导出数据和导入数据
    SQL LOADER 的用法 TXT文件导入非常之快
    在线代码对比/匹配 代码对比 在线文本比较
    JAVA 调用命令并输出
    RFC总结-SD模块
    使用BAPI_ACC_DOCUMENT_POST,创建会计凭证,用BADI扩展字段(转)
  • 原文地址:https://www.cnblogs.com/telecasterfanclub/p/13308412.html
Copyright © 2020-2023  润新知