今日内容 jwt的使用
-
Cookie,Session,Token介绍
Cookie
cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。
cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。
Session
session 从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。
session 也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用 cookie 的方式。
服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。
Cookie和Session的区别
session是存储服务器端,cookie是存储在客户端,所以session的安全性比cookie高
获取session里的信息是通过存放在会话cookie里的session id获取的。而session是存放在服务器的内存中里,所以session里的数据不断增加会造成服务器的负担,所以会把很重要的信息存储在session中,而把一些次要东西存储在客户端的cookie里。
session的信息是通过sessionid获取的,而sessionid是存放在会话cookie中
当浏览器关闭的时候会话cookie消失,所以sessionid也就消失了,但是session的信息还存在服务器端,只是查不到所谓的session,但它并不是不存在
Token
在Web领域基于Token的身份验证随处可见。在大多数使用Web API的互联网公司中,tokens 是多用户下处理认证的最佳方式。
以下几点特性会让你在程序中使用基于Token的身份验证
无状态、可扩展
支持移动设备
跨程序调用
安全
签发token:
验证token:
Token的组成与使用
组成:三段式
第一段:头
第二段:荷载(真正的数据信息)
第三段:签名(通过第一段和第二段,通过某种加密方式加密得到的 )
token的使用分为两个阶段
1.登录成功后的【签发token阶段】>>>生成三段
2.登陆成功访问某个接口的【验证阶段】>>>验证token是否合法
小总结
cookie:是存在客户端浏览器的键值对
session:是存在与服务端的键值对
token:三段式,服务端生成的,存放于客户端(浏览器就放在cookie中,移动端:存在移动端中)
-
JWT原理介绍
Json web token (JWT), token的应用于web方向的称之为jwt 构成和工作原理: JWT就是一段字符串,由三段信息构成的,将这三段信息文本用.链接一起就构成了Jwt字符串。就像这样: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ header:头 声明类型,这里是jwt 声明加密的算法 通常直接使用 HMAC SHA256 公司信息由{'typ':'JWT', 'alg':'HS256'} 变成了(base64的编码) eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9 paload:荷载 exp: jwt的过期时间,这个过期时间必须要大于签发时间 iat: jwt的签发时间 用户信息: 用户信息 由{ "exp": "1234567890","name": "John Doe", "userid": 3} 变成了(base64的编码) eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydW9 signature:签名 把头和荷载加密后得到的: TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
注意:
secret是保存在服务器端的(加密方式+盐),jwt的签发生成也是在服务器端的,secret就是用来进行jwt的签发和jwt的验证,所以,它就是你服务端的私钥,在任何场景都不应该流露出去。一旦客户端得知这个secret, 那就意味着客户端是可以自我签发jwt了
jwt使用流程最核心的是:
签发:登录接口签发
认证:认证类认证
-
base64编码和解码
base64 可以把字符串编码成base64的编码格式:(大小写字母,数字和 =)eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogImxxeiIsICJhZG1pbiI6IHRydWV9
base64可以把base64编码的字符串,解码回原来的格式
应用场景:
jwt中使用
网络中传输字符串就可以使用base64编码
网络中传输图片,也可能使用base64的编码
解码
# 把图片保存起来看看 import json import base64 d = {'name': 'lqz', 'userid': 6, 'age': 19} info = json.dumps(d) print(info) # 把字符串使用base64编码 res=base64.b64encode(info.encode('utf-8')) print(res) # eyJuYW1lIjogImxxeiIsICJ1c2VyaWQiOiA2LCAiYWdlIjogMTl9 res=base64.b64decode(s) with open('code.png','wb') as f: f.write(res)
-
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
-
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', } # 以后登录接口返回的格式就是咱们写的函数的返回值
-
自定义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.response import Response 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('用户名或密码错误')
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?