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

img

img

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

image

image

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',
}

测试结果

image

image

image

posted @ 2022-10-12 21:38  名字长的像一只老山羊  阅读(41)  评论(0编辑  收藏  举报