DRF—JWT:状态保持
实现状态保持有两种方法:
在客户端存储信息使用cookie
在服务器端存储信息使用session
Cookie:本质——>文件
Cookie是由服务器端生成,发送给浏览器,
浏览器会将Cookie的key/value保存到某个目录下的文本文件内,
下次请求同一网站时自动发送该Cookie给服务器
Cookie可以用来在某个WEB站点会话间持久地保持状态
session:依赖于cookie
Session是另一种记录客户状态的机制,基于Cookie实现,
不同的是Cookie保存在客户端浏览器中,而Session保存在服务器上
客户端浏览器访问服务器的时候,服务器把客户端信息以某种形式记录在服务器上,
这就是 Session
客户端浏览器再次访问时只需要从该Session中查找该客户的状态就可以了。
当服务器使用了负载均衡的时候,多台服务器使用的都是同一套网站的代码,用户请求网 站时,请求会被分发到不同的服务器上
这种情况下,用户第一次请求时,在A服务器生成了Sessionid,但在B服务器和C服务器并没有生成Sessionid,此时就会导致用户的登录状态出现问题,各服务器之间不能保持一致
cookie:None(为空时)
登录时——>发送request请求——>后台——>1)验证用户名和密码——>返回前端
(username,password) 2)生成sessionid
3)保存在服务器本地
4)返回数据—>原数据
session数据—>cookie
——>1)原始数据
2)session—>cookie
(登录后)前端——>发送request请求——>后台——>1)取session
(json,cookie) 2)验证用户名和密码
3)json处理
4)session+json返回
Token
JWT:Json Web Token(头部,载荷,签名)
头部—>加密
载荷—>解密
签证—>头部+载荷+头部里的加密方式+随机字符串(只有后台知道)
|
新的加密的字符串—>只可以加密不可以解密
登录前——>username,password——>登录后——>1)验证用户名和密码
2)生成Token
3)返回
登录前——>头部,json——>登录后——>1)验证Token
2)处理json
3)返回
Django用户模块
DRF—JWT:状态保持
使用django自己的用户模块
- 建立model
from django.contrib.auth.models import AbstractUser
- settings指定模型类
AUTH_USER_MODEL = 'jwtuserapp.JWTUser' # 指定使用jwtuserapp中的 model
- 迁移生成数据库(原来生成过这些表的,需要删除所有的表进行重新生成)
使用DRF—JWT来登录注册以及状态保持
- 下载依赖
pip install djangorestframework-jwt
- 配置settings
REST_FRAMEWORK = { # 身份认证 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ), #全局配置JWT验证设置 # 'DEFAULT_PERMISSION_CLASSES': ( # 'rest_framework.permissions.IsAuthenticated', # ), } import datetime JWT_AUTH = { 'JWT_AUTH_HEADER_PREFIX': 'JWT', 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), 'JWT_RESPONSE_PAYLOAD_HANDLER': 'jwtuserapp.views.jwt_response_payload_handler', # 重新login登录返回函数 }
- 写注册生成token的代码
1)使⽤django的⽤户模型类
from jwtuserapp.models import JWTUser
2)密码要密⽂
from django.contrib.auth.hashers import make_password def post(self,request): # 获取数据,密码加密并存到数据库 data = request.data data1 = copy.deepcopy(data) old_pwd = data.get('password') new_pwd = make_password(old_pwd) data1['password'] = new_pwd ser = JWT_User_SER(data=data1) ser.is_valid(raise_exception=True) ser.save()
3)⽣成token并返回到前端
# 生成token user = JWTUser.objects.get(username=data1['username']) jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER payload = jwt_payload_handler(user) token = jwt_encode_handler(payload) print(token) # 将token和数据库的用户信息进行返回 response_data = ser.data response_data['JWTToken'] = token return Response({'code':200,'data':response_data})
- 登陆生成token的代码
1)url⾥导包,并指定url
from rest_framework_jwt.views import obtain_jwt_token # 验证密码后返回token path('login/',obtain_jwt_token),
2)view⾥写返回的数据有哪些
def jwt_response_payload_handler(token, user=None, request=None): ''' :param token: jwt生成的token值 :param user: User对象 :param request: 请求 ''' return { 'token': token, 'user': user.username, 'userid': user.id, 'nickname':user.nickname }
3)settings⾥配置并告知django
import datetime JWT_AUTH = { 'JWT_AUTH_HEADER_PREFIX': 'JWT', 'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1), 'JWT_RESPONSE_PAYLOAD_HANDLER': 'jwtuserapp.views.jwt_response_payload_handler', # 重新login登录返回函数 }
- 权限分离
1)导包
from rest_framework.permissions import IsAuthenticated,AllowAny
2)APIView⾥设置permissions_class