token与jwt
cookie、session、token
1.cookie、session是用于保存登录信息的,每个用户端只需要保存自己的session id,而服务器要保存所有人的session id,如果访问的用户端过多,这对服务器说是一个巨大的消耗
2.token就可以让每个客户端去保存直接的登录信息
2.1token三段式
-头:公司信息、加密方式...
-荷载:真正的数据{name:barry,id:1}
-签名:通过第一段和第二段,通过某种加密方式加密得到的字符串
2.2这个token服务端不保存,当用户端将token发来时,服务端在用同样的算法和秘钥,对数据在生成一个签名,在拿型生成的签名与token的签名进行比较,如果不同,那么数据肯定别篡改过了
3.cookie、session、token
cookie:储存于客户端浏览器的键值对
session:储存于服务端的键值对
token:服务端生成三段式,储存于客户端(浏览器就放在cookie中,移动端存放在移动端中)

jwt
jwt原理
1.Json web token (JWT), token的应用于web方向的称之为jwt
2.构成和工作原理
jwt是一串字符串,由三段信息构成的,将这三段信息文本yong'.'连接在一起就构成了jwt字符串
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
-第一段称之为头部(header),第二段称之为载荷(payload),第三段是签证(signature)
3.header
-声明类型
-声明加密的算法
-公司信息
-由{"exp": "1234567890",
"name": "John Doe",
"userid": 3}变成了(base64的编码)
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9
4.psyload
-exp:jwt的过期时间,这个过期时间必须要大于签发时间
-iat:iwt的签发时间
-用户信息:用户信息
-由{"exp": "1234567890",
"name": "John Doe",
"userid": 3}变成了(base64的编码)
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
5.signature
-把头和荷载加密得到
TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
'''
secret是保存在服务端的加密方式+盐,secret是用来进行jwt的签发和jwt的验证,它就是服务端的私钥,如果客户端得到这个secret,那就意味着客户端可以自我签发jwt
'''
6.基于session的认证机制
.1登录
-校验用户是否登录成功
-生成一个随机字符串,将随机字符串存入django-session表中
-将随机字符串作为cookie,返回给浏览器
.2访问
-携带sessionid=随机字符串
-取出随机字符串,在去django-session表中取出数据
-转换为session对象(字典),在视图类中就可以使用
7.基于jwt的认证
.1登录
-校验用户是否登录成功
-签发token(头.荷载.签名)
-返回给客户端保存
.2访问
-携带token访问接口
-取出token(取出头、荷载使用同样的方法生成签名)
-把token的签名与新生成的token验证
-验证通过在取出用户id,去数据库查出当前登录用户
base64编码和解码
1.base64可以把字符串编码成base64的编码格式,或将base64编码的字符串,解码回原来的格式
'eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogImxxeiIsICJhZG1pbiI6IHRydWV9'
2.常用场景
-jwt中使用
-网络中传输字符串可以使用
-网络中传输图片可以使用
3.编码解码
import json, base64
d1 = {'name': 'barry', 'age': '20'}
# 将字典转换为json字符串格式
info = json.dumps(d1)
# 将字符串转换为bytes格式,在编码成base64的编码格式
res = base64.b64encode(info.encode('utf-8'))
print(res)
# b'eyJuYW1lIjogImJhcnJ5IiwgImFnZSI6ICIyMCJ9'
# 将base64编码的字符串解码回原来的格式
ser = base64.b64decode('eyJuYW1lIjogImJhcnJ5IiwgImFnZSI6ICIyMCJ9')
print(ser)
# b'{"name": "barry", "age": "20"}'
drf-jwt快速使用
1.django中使用jwt
'jwt签发(登录接口)、认证(认证类)'
https://github.com/jpadilla/django-rest-framework-jwt
https://github.com/jazzband/djangorestframework-simplejwt
2.安装
pip3 install djangorestframework-jwt
3.快速使用
-迁移表在创建创建用户,它默认使用auth的user表签发token
-不需要写登录接口,使用auth的user表作为用户表,它可以快速签发
-签发(登录):只需要在路由中配置,它会帮我们写好登录接口
from rest_framework_jwt.views import obtain_jwt_token
urlpatterns = [
path('login/', obtain_jwt_token),
]
-认证(认证类):
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
class TestView(APIView):
# 添加认证类
authentication_classes = [JSONWebTokenAuthentication]
# 要使用jwt提供的认证类必须配合权限类
permission_classes = [IsAuthenticated]
def get(self, request):
return Response('yes')
-前端访问时,token需要放在请求头中
KEY不是token而是Authorization
VALUE的token串需要在前面加jwt空格---》'jwt token串'
drf-jwt修改返回格式
1.登录成功后,前端的返回格式改为我们想要的格式
{code:100,msg:'登录成功',token:字符串}
2.写个函数
def jwt_response_payload_handler(token, user=None, request=None):
return {
'code': 100,
'msg': '登录成功',
'username': user.username,
'toke': token
}
3.把函数配置在配置文件中
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.response.jwt_response_payload_handler',
}
4.签发的token是有过期时间的,默认是5分钟,可以在配置文件中自定义token过期时间
JWT_AUTH = {
# 修改token的过期时间,设置为1天
'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
}
自定义user表,签发token
1.models.py,定义表
class UserInfo(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
2.views.py,写一个接口
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
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)
# 使用rest_framework_jwt模块提供的签发token的函数来生成token
# 通过user对象得到{username,id,过期时间}
payload = jwt_payload_handler(user)
# 根据payload得到token(头.荷载.签名)
token = jwt_encode_handler(payload)
return Response({'code': 100, 'msg': '登录成功', 'token': token})
except Exception as e:
raise APIException('用户名或密码错误')
作业
1 快速签发
2 修改返回格式
3 自定义用户表签发token
4 自定义认证类,验证token(尽量写)
try:
payload = jwt_decode_handler(jwt_value)
except jwt.ExpiredSignature:
msg = _('Signature has expired.')
raise exceptions.AuthenticationFailed(msg)
except jwt.DecodeError:
msg = _('Error decoding signature.')
raise exceptions.AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise exceptions.AuthenticationFailed()
user=payload.get('user_id')
return user,token
--------有兴趣-----
# 请求头中:X_FORWARDED_FOR 代之什么?
-X-Forwarded-For 是一个 HTTP 扩展头部。用来表示 HTTP 请求端真实 IP。
-请求头格式:X-Forwarded-For: client, proxy1, proxy2, proxy3
-最开始的是离服务端最远的设备 IP,然后是每一级代理设备的 IP
-服务端最终会收到:X-Forwarded-For: IP0, IP1, IP2
-经过了三个代理 Proxy1、Proxy2、Proxy3的IP分别为 IP1、IP2、IP3,用户真实 IP 为 IP0
# 集群 ,分布式
1.集群
-单机处理到达瓶颈的时候,你就把单机复制几份,这样就构成了一个“集群”。集群中每台服务器就叫做这个集群的一个“节点”,所有节点构成了一个集群。每个节点都提供相同的服务,那么这样就相当于提升了系统的处理能力
1.1负载均衡
-在所有节点之前增加一个“调度者”的角色,用户的所有请求都先交给它,然后它根据当前所有节点的负载情况,决定将这个请求交给哪个节点处理。这个“调度者”就叫——负载均衡服务器
2.分布式
-分布式结构就是将一个完整的系统,按照业务功能,拆分成一个个独立的子系统,在分布式结构中,每个子系统就被称为“服务”
-假设需要开发一个在线商城。我们需要按照功能模块拆分成多个独立的服务,如:用户服务、产品服务、订单服务、后台管理服务等等。这一个个服务都是一个个独立的项目,可以独立运行
4
1.认证类
from .models import UserInfo
import jwt
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from django.utils.translation import ugettext as _
from rest_framework_jwt.settings import api_settings
jwt_decode_handler = api_settings.JWT_DECODE_HANDLER
class Authentication(BaseAuthentication):
def authenticate(self, request):
# 从请求头中取出token
token = request.META.get('HTTP_TOKEN')
# 是否携带token
if token:
# 验证token是否过期、是否被篡改
try:
payload = jwt_decode_handler(token)
except jwt.ExpiredSignature:
msg = _('签名已经过期')
raise AuthenticationFailed(msg)
except jwt.DecodeError:
msg = _('签名被篡改')
raise AuthenticationFailed(msg)
except jwt.InvalidTokenError:
raise AuthenticationFailed('未知错误')
# 通过payload获取当前登录用户
user = UserInfo.objects.filter(pk=payload.get('user_id')).first()
print(user)
return user, token
else:
raise AuthenticationFailed('你没有携带token')
2.视图类
class TestView(APIView):
# 添加认证类
authentication_classes = [Authentication]
def get(self, request):
return Response('yes')
标签:
drf
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?