【2022.10.12】drf(10)

今日内容

  • 1、cookie session token 介绍
  • 2、jwt介绍
  • 3、base64编码和解码
  • 4、drf-jwt快速使用
  • 5、drf-jwt修改返回格式
  • 6、自定义suer表、签发token

1.cookie session token介绍

cookie是:存在客户端浏览器的键值对
session是:存在于服务端的键值对
token是:三段式,服务端生成的,存放在客户端(浏览器就放在cookie中,移动端:存在移动端中)

第一段:头:公司信息,加密方式
第二段:荷载:真正的数据 例如:{name:wym,age:20}
第三段:签名,通过第一段和第二段,通过某种加密方式加密得到 例如:dadanczkawdkfn 

token的使用分为两个阶段
1.登录成功后【签发token阶段】---> 生成第三阶段
2.登录成功访问某个接口的【验证阶段】--->去验证token是否合法

# 注意:使用token的认证机制,服务端还要储存数据吗?token是服务的生成,客户端保存,服务端不存储token

token的第一阶段解读流程

img

token的第二阶段解读流程

img

2.jwt原理介绍

  • 简介:Json web token(JWT),token的应用于web方向的称之为 jwt
# jwt的构成和工作原理

# 构成:
    JWT就是一段字符串呢,由三段信息构成的,将这三段信息文本用 . 连接起来就构成了JWT字符串,例如:eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
    # header:头
    
    1.声明类型,这里是jwt
    2.声明加密的算法 通常直接使用 HMAC SHA256
    3.公司信息
    例如下:
    {
        'typ':'JWT',
        'alg':'HS256',
        
    }
    编译成base64的编码:
    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
    
    
    # payload:荷载
    
    1.exp: jwt的过期时间,这个过期时间必须要大于签发时间
    2.iat: jwt的签发时间
    3.用户信息: 用户信息
     例如下:
     {
          "exp": "1234567890",
          "name": "John Doe",
          "userid": 3
      }
       变成了(base64的编码)
       eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
        
    # signature:签名
    	
        把头和荷载加密后得到的:TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
    

# 注意:secret是保存在服务器端的(加密方式+盐),jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了
    
    
    
    
 # jwt使用流程最核心的是:
	-签发:登录接口签发
    -认证:认证类认证

基于jwt的认证机制

基于session的认证机制

3.base64编码和解码

  • 1、简介:base64 可以把字符串编码成base64的编码格式:(大小写字母,数字和 =)
  • 2、解码原理:base64可以把base64编码的字符串,解码回原来的格式
  • 3、应用场景:
    • jwt中使用:
    • (1)网络中传输字符串就可以使用base64编码
    • (2)网络中传输图片,也可能使用base64的编码
#base64编码:

import json
import base64
d = {'name':'jason','age':20}
a = json.dumps(d) # 序列化json格式字符串
# 第一种编码方式用.encode 转成utf-8
res = base64.b64encode(a.encode('utf-8'))
print(res)
# 第二种编码方式用.encoding 转成utf-8
res1 = base64.b64encode(bytes(a, encoding='utf-8'))
print(res1)  # b'eyJuYW1lIjogImphc29uIiwgImFnZSI6IDIwfQ=='

# base64解码:
res2 = base64.b64decode('eyJuYW1lIjogImphc29uIiwgImFnZSI6IDIwfQ==')
print(json.loads(res))


# base64图片解码:
# d 为图片base64的编码
d= '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'
res = base64.b64decode(d)
with open('logo.png','wb')as f:
    f.write(res)

4、 drf-jwt快速使用

# jwt:签发(登录接口) 认证(认证类)
# django中使用jwt
	-可以自己写
    -https://github.com/jpadilla/django-rest-framework-jwt  (比较老)
    -https://github.com/jazzband/djangorestframework-simplejwt (比较新)
    
    
    
# 安装
	pip3 install djangorestframework-jwt
# 快速使用
	-迁移表,因为它默认使用auth的user表签发token
    -创建超级用户(auth的user表中要右记录)
    -咱们不需要写登录接口了,如果是使用auth的user表作为用户表,它可以快速签发
    -签发(登录):只需要在路由中配置(因为它帮咱们写好登录接口了)
    from rest_framework_jwt.views import obtain_jwt_token
    urlpatterns = [
        path('login/', obtain_jwt_token),
    ]
    -认证(认证类):导入,配置在视图类上
    	class TestView(APIView):
            authentication_classes = [JSONWebTokenAuthentication,]
            permission_classes = [IsAuthenticated,]
            
    -前端访问时,token需要放在请求头中
    	Authorization:jwt token串
    

5、drf-jwt修改返回格式

# 登录成功后,前端看到的格式,太固定了,只有token,我们想做成
	{code:100,msg:'登录成功',token:adfasdfasdf}
    
    
# 固定写法:写一个函数,函数返回什么,前端就看到什么,配置在配置文件中

# 使用步骤:
	-1 写一个函数
    def jwt_response_payload_handler(token, user=None, request=None):
        return {
            'code':100,
            'msg':'登录成功',
            'username':user.username,
            'token':token
        }
     -2 把函数配置在配置文件中
        JWT_AUTH={
        'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.response.jwt_response_payload_handler',
    	}
        
 # 以后登录接口返回的格式就是咱们写的函数的返回值

6、自定义user表,签发token

# models.py 中定义UserInfo表

class UserInfo(models.Model):
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)

# 写一个登录接口
from rest_framework.exceptions import APIException

from rest_framework_jwt.settings import api_settings
jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER


from .models import UserInfo
class UserView(APIView):
    def post(self, request):
        try:
            username = request.data.get('username')
            password = request.data.get('password')
            user=UserInfo.objects.get(username=username,password=password)
            # 根据user,签发token---》三部分:头,荷载,签名
            # 使用djagnorestframework-jwt模块提供的签发token的函数,生成token
            payload = jwt_payload_handler(user) # 通过user对象---》{username:lqz,id:1,过期时间}
            token=jwt_encode_handler(payload) # 根据payload---》得到token:头.荷载.签名
            print(payload)
            print(token)

            return Response({'code':100,'msg':'登录成功','token':token})
        except Exception as e:
            raise APIException('用户名或密码错误')
posted @   W日常  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)
点击右上角即可分享
微信分享提示