drf 接口文档 jwt介绍和原理 drf-jwt快速使用 定制返回格式 jwt认证类

昨日内容

# 1 认证类的执行流程--->源码分析
-请求进来--->路由匹配成功--->执行path('text/',view.BookView.as_view()),--->继承了APIView--->APIView的as_view()内部的闭包函数view--->这个view中执行了self.dispatch--->APIView的dispatch--->

    def dispatch(self, request, *args, **kwargs):
        # 包装了新的request
        request = self.initialize_request(request, *args, **kwargs)
        。。。
        # 执行3大认证
        self.initial(request, *args, **kwargs)
        # 下面执行视图类的方法
    def initial(self, request, *args, **kwargs):
        # 认证
        self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request)
	def perform_authentication(self, request):
        request.user
     
    
 	####### Request 新的Request内部找  user
    @property
    def user(self):
        if not hasattr(self, '_user'):
            with wrap_attributeerrors():  # 上下文管理器----》面试
                self._authenticate()
        return self._user
   

   ### 核心代码
    def _authenticate(self):
        # self.authenticators---》列表[认证类对象1,认证类对象2]
        # authenticator 是认证类的对象
        for authenticator in self.authenticators:
            try:
                #认证类对象.authenticate   self 是新的request对象
                user_auth_tuple = authenticator.authenticate(self)
            except exceptions.APIException:
                self._not_authenticated()
                raise

            if user_auth_tuple is not None:
                self._authenticator = authenticator
                #self 是新的request
                # request.user 就是当前登录用户
                # request.auth 一般把token给它
                self.user, self.auth = user_auth_tuple
                return
        self._not_authenticated()
 

  # self.authenticators:是什么时候传入的?执行__init__ 就是在Request初始化的时候传入的
	-在APIView的dispatch的self.initialize_request(request, *args, **kwargs)初始化的,
     return Request(
            request,
            parsers=self.get_parsers(),
         	#在这里传入的
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
    -APIView的--get_authenticators()----》return [auth() for auth in self.authentication_classes]
    
    -self.authentication_classes:视图类中配置的一个个的认证类的列表,如果没配,配置文件中,内置配置文件中
    
# 2 权限类的执行流程


# 3 频率类的执行流程


# 4 自己定义一个频率类,基于BaseThrottle,重写allow_request

# 5 SimpleRateThrottle
-继承它,写的代码少
-只需要重写get_cache_key和scope类属性,配置文件配置
-源码:allow_request--->就是咱们上面写的,可扩展性高,好多东西从配置文件取的
    
# 6 全局异常处理
-源码中,在3大认证,视图类的方法中如果出错,就会执行:
self.handle_exception(exc)
     def handle_exception(self, exc):
        # 去配置文件中找到:EXCEPTION_HANDLER对应的函数,exception_handler
        exception_handler = self.get_exception_handler()
        # exception_handler(exc,context)
        response = exception_handler(exc, context)
        return response
    
-自己在配置文件中配置,以后出了异常,走自己的,有两个参数exc,context
-exc错误对象
-context:上下文,包含 view,request。。。
  • 接口文档

  • jwt介绍和原理

  • drf-jwt快速使用

  • 定制返回格式

  • jwt的认证类

1 接口文档

# 全后端分离
    -我们做后端,写接口
    -前端做前端,根据接口写app,pc,小程序

    -作为后端来讲,我们很清楚,比如登录接口  /api/v1/login/---->post---->username,password 编码方式json---->返回格式 {code:100,msg:登陆成功}
    
    -后端人员,接口写完,一定要写接口文档
    
# 接口文档如何编写
    -1 使用word,md 编写接口文档
    -2 使用第三方平台,编写我们接口文档(非常多)--->收费
    -3 公司自己使用第三方开源的搭建的--->Yapi--->你如果向自己搭建
       -https://zhuanlan.zhihu.com/p/366025001 
     
    -4 使用drf编写的接口,可以自动生成接口文档
        -swagger--->drf-yasg--->官方推荐使用
        -coreapi
# 使用coreapi自动生成接口文档步骤
1 安装 pip install coreapi
2 配置路由
      from rest_framework.documentation import include_docs_urls
       path('docs/',include_docs_urls(title='xx项目接口文档')),  
3 在视图类,方法上,写注释即可
    -在类上加注释
    -在类的方法上加注释
    -在序列化类或表模型的字段上加 help_text,required...

image-20230209173255543

image-20230209173345061

4 配置文件配置
  REST_FRAMEWORK = {
           'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',
            }

image-20230209173558404

5 访问地址:http://127.0.0.1:8000/docs

image-20230209173700724

总结

# 接口文档,需要有的东西
-描述
-地址
-请求方式
-请求编码格式
-请求数据详解(必填,类型)
-返回格式案例
-返回数据字段解释
-错误码

2 jwt介绍和原理

# Json web token (JWT)  就是web方向token的使用
# cookie,session,token
   -cookie是存放在客户端浏览器的键值对
   -session是存放在服务端的键值对
      客户端:sessionId:asdasds---->放到cookie中
      服务端:asdasds:{id:1,name:lqz}
   -token:字符串:分三段
      -头:header
        声明类型,这里是jwt
		声明加密的算法 通常直接使用 HMAC SHA256
        公司信息。。。
      -荷载:payload
    	-存放有效信息的地方
        -过期时间
        -签发时间
        -用户id
        -用户名字。。。
	  -签名:signature
    	-第一部分和第二部分通过秘钥+加密方式得到的
        
      -token的【签发】:登陆成功后,服务端生成
      -把token生成的字符串给前端
      -后面前端只要发请求,就携带token字符串到后端
    
      -token的【验证】:--->拿到第一部分和第二部分使用同样的加密方式+密钥再加密--->得到字符串跟第三段比较,如果一样,表示没有被篡改,如果不一样,表明被篡改了,token不能用了
      -如果没有被篡改,取出第二段  当前登录用户的信息  id
#jwt:Json web token---》只针对于web方向的token方式验证

#JWT的构成 三部分,每部分用 .  分割
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

2.1 base64编码和解码

编码

import base64
import json

dic = {'user_id': 1, 'username': 'lqz'}
dic_str = json.dumps(dic)
# 把这个字符串使用base64编码
res = base64.b64encode(dic_str.encode('utf8'))
print(res)

image-20230209195006037

解码

# 注意:base64编码后,字符长度一定是4的倍数,如果不是,使用  =  补齐,  = 不表示数据
res = base64.b64decode('eyJ1c2VyX2lkIjogMSwgInVzZXJuYW1lIjogImxxeiJ9=')
print(res)

image-20230209195243454

base64 应用场景

1 jwt 使用了base64
2 网络中传输数据,也会经常使用 base64编码
3 网络传输中,有的图片使用base64编码

image-20230209195903766

3 drf-jwt快速使用

#django+drf 平台开发jwt这套,有两个模块
	-djangorestframework-jwt  ---》一直可以用
    -djangorestframework-simplejwt---》公司用的多
    -自己封装jwt签发和认证
    
# 使用步骤
1 安装
pip3 install djangorestframework-jwt

2 快速使用---》使用的表是django的auth的user表---》创建一个用户

3 只需要在路由中配置---》auth的user表中有用户
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
    path('login/', obtain_jwt_token),
]

4 postman,向http://127.0.0.1:8000/login/发送post请求,携带username和password

image-20230209210925969

4 定制返回格式

# 以后,如果是基于auth的User表签发token,就可以不自己写了,但是登录接口返回的格式,只有token,不符合公司规范
1 写个函数:jwt_response_payload_handler

def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'code': 100,
        'msg': '登录成功',
        'token': token,
        'username': user.username
    }

image-20230209213809534

2 配置一下 ,项目配置文件
    JWT_AUTH = {
    	'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.utils.jwt_response_payload_handler',  
	}

image-20230209213844412

3 使用postman测试,就能看到返回的格式了

image-20230209213902489

5 jwt的认证类

# 以后接口要登录后才能访问的使用
1 在视图类上加一个认证类,一个权限类

from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated


class BookView(ViewSetMixin, RetrieveAPIView, CreateAPIView, DestroyAPIView, UpdateAPIView, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 使用drf-jwt提供的认证类  我们觉得,加了它,就有登录认证了
    authentication_classes = [JSONWebTokenAuthentication]
    # 必须要配合一个权限类--->drf的提供的权限类
    permission_classes = [IsAuthenticated]  # 登录用户有权限 不登陆用户没有权限

image-20230209220950271

2 postman测试
    	-请求头中key值叫Authorization
        -请求头的value值是:jwt+空格+有效的token值

image-20230209221046695

6 simplejwt

# 路由导入simplejwt
from rest_framework_simplejwt.views import token_obtain_sliding

path('login/', token_obtain_sliding),

image-20230209224338789

settings.py

认证生成token的属性不同,解析的时候也是不同的,所以需要配置相同的认证token属性的类,其实就是对象加密属性

SIMPLE_JWT = {
    "AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.SlidingToken",),  # 这个需要跟你路由中使用的生成类是一个
    # 这个是定制值的第一个字符串
    "AUTH_HEADER_TYPES": ("qwe",),
    # 这个是定制请求头字符串
    "AUTH_HEADER_NAME": "HTTP_QWE",
}

image-20230209224808302

image-20230209224746085

view.py

from rest_framework.permissions import IsAuthenticated
from rest_framework_simplejwt.authentication import JWTAuthentication


class BookView(ViewSetMixin, RetrieveAPIView, CreateAPIView, DestroyAPIView, UpdateAPIView, ListAPIView):
    queryset = Book.objects.all()
    serializer_class = BookSerializer
    # 使用drf-jwt提供的认证类  我们觉得,加了它,就有登录认证了
    authentication_classes = [JWTAuthentication]
    # 必须要配合一个权限类--->drf的提供的权限类
    permission_classes = [IsAuthenticated]  # 登录用户有权限 不登陆用户没有权限

image-20230209224953768

postman测试
    	-请求头中key值叫qwe
        -请求头的value值是:qwe+空格+有效的token值

image-20230209225059120

posted @ 2023-02-09 22:15  Super小赵  阅读(96)  评论(0编辑  收藏  举报
****************************************** 页脚Html代码 ******************************************