drf10cookie,session,token jwt原理介绍 base64b编码和解码 drf-jwt的快速使用 drf-jwt修改返回格式 自定义user表,签发token
cookie,session,token
jwt原理介绍、
base64b编码和解码
drf-jwt的快速使用
drf-jwt修改返回格式
自定义user表,签发token
cookie,session,token介绍
token: 三段式
第一段: 头:公司信息,加密方式。。。{}
第二段:荷载:真正的数据{name:lqz,id:1}
第三段:签名,通过第一段和第二段,通过某种加密方式加密得到的
-----------------------------------------------------------------------------
token的使用分两个阶段
-登录成功后的【签发token阶段】---》生成三段
-登录成功访问某个接口【验证段】---》验证token是否合法
---------------------------------------------------------------------------
cookie: 存在客户端浏览器的键值对
session:存在于服务端的键值对
token是:三段式,服务端生成的,存放在客户端(浏览器就放在cookie中,移动端放在移动端中)、
使用token的认证机制,服务端还要存数据吗,token是服务的生成,客户端保存,服务端不存储token
jwt
jwt原理介绍
#json web token(JWT),token的应用于web方向的称之为jwt
构成和原理
jwt就是一段字符串,由三段信息构成的,将这三段信息文本用,链接一起就构成了jwt字符串,就像这样
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
#header:头
-声明类型,这里是jwt
-声明加密的算法,通常直接使用 HMAC,SHA256
-公司信息
由
{
'type':'JWT',
'alg':'HS256',
}
变成了(base64的编码)
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
#payload: 荷载
exp: jwt的过期实际,这个过期必须必须要大于签发实际
iat: jwt的签发时间
用户信息:用户信息由
{
"exp":"1234567890",
"name":"john Doe",
"userid":3
}
变成了(base64的编码)
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
#signature: 签名
把头和荷载加密后得到的:TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ
base64编码和解码
#base64 可以把字符串编码成base64的编码格式:(大小字母,数字和=
eyJzdWIiOiAiMTIzNDU2Nzg5MCIsICJuYW1lIjogImxxeiIsICJhZG1pbiI6IHRydWV9)
#base64 可以把base64编码的字符串,解码回原来的格式
编码解码
import json
import base64
#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)
#base64解码
res
=base64.b64decode(b'eyJuYW1lIjogImx6bCIsICJ1c2VyaWQiOiA2LCAiYWdlIjogMTl9')
print(res)
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 (比较新)
安装
pip install djangorestframework-jwt
快速使用
-迁移表,默认使用auth的user表签发token
-创建超级用户(auth的user表中要有记录)
不需要写登录接口,如果使用auth的user表作为用户表,它可以快速签发
-签发(登录):只需要在路由中配置(它我们写好登录接口了)
from rest_framework_jwt.views import obtain_jwt_token
url_patterns = [path('login/',obtain_jwt_token),]
-认证(认证类):导入配置在视图类中
class TestView(APIView):
authentication_class = [JSONWebTokenAuthentication,]
permission_class = [isAuthenticated,]
-前端访问时,token需要放在请求头中
Authorization: jwt token串
drf-jwt修改返回格式
#登录成功后,前端看到的格式太固定了,只有token,我们想做成
{code:10,msg:'登录成功',token:adfasdfasd}
固定写法:写一个函数,函数返回什么,前端就看到什么,配置文件中
使用步骤:
写一个函数
def jwt_response_payload_handle(token,user=None,request=None):
return {
'code':100,
'msg':'登录成功',
'username':user.username,
'token':token
}
-2 把函数配置在settings配置文件中
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,passowrd=password)
#根据user,签发token-->>三部分,头,荷载,签名
#使用djangorestframework-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('用户名或密码错误')
练习
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 代之什么?
# 集群 ,分布式
练习
快速签发并修改返回格式
1.创建超级管理员,使用auth的表,并且修改jango-jwt返回格式
urls.py
from django.contrib import admin
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
from app01 import views
urlpatterns = [
path('admin/', admin.site.urls),
path('login/',obtain_jwt_token),
path('test/',views.TestView.as_view()),
]
views.py
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
class TestView(APIView):
authentication_classes = [JSONWebTokenAuthentication, ]
permission_classes = [IsAuthenticated, ]
def get(self, request):
return Response('ok')
新建一个python文件写返回jwt响应返回函数
jwt_response.py
def jwt_response_payload_handler(token, user=None, request=None):
return {
'code': 100,
'msg': '登录成功',
'username': user.username,
'token': token
}
settings.py
JWT_AUTH = {
'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.jwt_response.jwt_response_payload_handler',
}
测试结果