Ⅰ simple-jwt快速使用
【一】安装
pip3 install djangorestframework- simplejwt
【二】快速使用
python manage. py createsuperuser
from django. urls import path
from rest_framework_jwt. views import obtain_jwt_token
urlpatterns = [
path( 'login/' , obtain_jwt_token) ,
]
向后端接口发送post请求,携带用户名密码,即可看到生成的token
【三】双token认证
【1】双token介绍
- 一个token 时间很久 比如 7 天 refresh
- 一个token 时间很多 比如 3 分钟 access
- 只要登录后才能访问的接口- - > 要携带 access- - token- - > 3 分钟后过期了,不能用了
- 一旦access过期,发送请求携带refresh- - > token- - - > 通过refresh- - > 签发一个新的access- - > 发送请求使用access
import base64
res= base64. b64decode( "eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzIyNzQ2MDYzLCJpYXQiOjE3MjI3NDU3NjMsImp0aSI6IjkwYjk0ZDU5NjUwZTQ0YWI4ODlkNDBhYzEwZjJlYjViIiwidXNlcl9pZCI6MX0=" )
print ( res)
【2】双token认证使用
- 签发:路由配置- - > 帮写了登录
from rest_framework_simplejwt. views import token_obtain_pair
urlpatterns = [
path( 'login/' , token_obtain_pair) ,
]
- 认证:
class BookView ( APIView) :
authentication_classes = [ JWTTokenUserAuthentication]
permission_classes = [ IsAuthenticated]
- 如果不加权限类,执行逻辑是:
- 如果携带了token- - - > 就去校验- - > 如果有错就会报错
- 如果没有携带token- - > 根本不校验- - > 所以如果只配置JWTTokenUserAuthentication,用户不带登录信息,是不做校验的
from rest_framework. views import APIView
from rest_framework. response import Response
from rest_framework_simplejwt. authentication import JWTTokenUserAuthentication
from rest_framework. permissions import IsAuthenticated
class BookView ( APIView) :
authentication_classes = [ JWTTokenUserAuthentication]
permission_classes = [ IsAuthenticated]
def get ( self, request) :
return Response( "很多玉树" )
只不过携带的不是token是Authorization
key: Authorization
value: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9. eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzIyNzQ3NDc2LCJpYXQiOjE3MjI3NDcxNzYsImp0aSI6ImJhYzIzMTk3M2E1ZDQ1ZjhiMmY1MGZjMzU3NzM0NjUyIiwidXNlcl9pZCI6MX0. dkZhY19kbR1g7XKwaDOrxZHBhWJJQ40Liid5f3VK7aU
【四】更新access
urlpatterns = [
path( 'refresh/' , token_refresh) ,
]
Ⅱ simple-jwt配置文件
SIMPLE_JWT = {
'ACCESS_TOKEN_LIFETIME' : timedelta( minutes= 5 ) ,
'REFRESH_TOKEN_LIFETIME' : timedelta( days= 7 ) ,
'ROTATE_REFRESH_TOKENS' : False ,
'BLACKLIST_AFTER_ROTATION' : False ,
'ALGORITHM' : 'HS256' ,
'SIGNING_KEY' : settings. SECRET_KEY,
"UPDATE_LAST_LOGIN" : False ,
"VERIFYING_KEY" : "" ,
"AUDIENCE" : None ,
"ISSUER" : None ,
"JSON_ENCODER" : None ,
"JWK_URL" : None ,
"LEEWAY" : 0 ,
"AUTH_HEADER_TYPES" : ( "Bearer" , ) ,
"AUTH_HEADER_NAME" : "HTTP_AUTHORIZATION" ,
"USER_ID_FIELD" : "id" ,
"USER_ID_CLAIM" : "user_id" ,
"USER_AUTHENTICATION_RULE" : "rest_framework_simplejwt.authentication.default_user_authentication_rule" ,
"AUTH_TOKEN_CLASSES" : ( "rest_framework_simplejwt.tokens.AccessToken" , ) ,
"TOKEN_TYPE_CLAIM" : "token_type" ,
"TOKEN_USER_CLASS" : "rest_framework_simplejwt.models.TokenUser" ,
"JTI_CLAIM" : "jti" ,
"SLIDING_TOKEN_REFRESH_EXP_CLAIM" : "refresh_exp" ,
"SLIDING_TOKEN_LIFETIME" : timedelta( minutes= 5 ) ,
"SLIDING_TOKEN_REFRESH_LIFETIME" : timedelta( days= 1 ) ,
"TOKEN_OBTAIN_SERIALIZER" : "rest_framework_simplejwt.serializers.TokenObtainPairSerializer" ,
"TOKEN_REFRESH_SERIALIZER" : "rest_framework_simplejwt.serializers.TokenRefreshSerializer" ,
"TOKEN_VERIFY_SERIALIZER" : "rest_framework_simplejwt.serializers.TokenVerifySerializer" ,
"TOKEN_BLACKLIST_SERIALIZER" : "rest_framework_simplejwt.serializers.TokenBlacklistSerializer" ,
"SLIDING_TOKEN_OBTAIN_SERIALIZER" : "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer" ,
"SLIDING_TOKEN_REFRESH_SERIALIZER" : "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer" ,
}
from datetime import timedelta
SIMPLE_JWT= {
'ACCESS_TOKEN_LIFETIME' : timedelta( minutes= 60 ) ,
'REFRESH_TOKEN_LIFETIME' : timedelta( days= 7 ) ,
}
Ⅲ 定制登录返回格式
【一】定制返回格式
{ code: 100 , msg: 登录成,token: asdfa. asdfa. asdfasd}
1 写个序列化类,重写validate方法,方法返回什么,登录成功的格式就是什么
- 如下
2 配置文件配置:
SIMPLE_JWT= {
"TOKEN_OBTAIN_SERIALIZER" : "app01.serialzier.MyTokenObtainPairSerializer" ,
}
from rest_framework_simplejwt. serializers import TokenObtainPairSerializer
from rest_framework_simplejwt. views import TokenObtainPairView
class MyTokenObtainPairSerializer ( TokenObtainPairSerializer) :
def validate ( self, attrs) :
"""
自定义返回的格式
self.user 就是当前登录用户
super().validate(attrs) 返回的数据是个字典:有refresh access
"""
old_data = super ( ) . validate( attrs)
data = { 'code' : 100 ,
'msg' : '登录成功成功' ,
'username' : self. user. username,
'token' : old_data. get( 'access' ) ,
}
return data
【二】更改荷载
【1】模板
【1 】 写个序列化类,重写validate方法, 重新一个类方法
@classmethod
def get_token ( cls, user) :
token = super ( ) . get_token( user)
token[ 'name' ] = user. username
return token
【2 】 配置文件配置:
SIMPLE_JWT= {
"TOKEN_OBTAIN_SERIALIZER" : "aoo01.serialzier.MyTokenObtainPairSerializer" ,
}
【2】使用
from rest_framework_simplejwt. serializers import TokenObtainPairSerializer
from rest_framework_simplejwt. views import TokenObtainPairView
class MyTokenObtainPairSerializer ( TokenObtainPairSerializer) :
@classmethod
def get_token ( cls, user) :
token = super ( ) . get_token( user)
token[ 'name' ] = user. username
token[ 'email' ] = user. email
return token
def validate ( self, attrs) :
"""
自定义返回的格式
self.user 就是当前登录用户
super().validate(attrs) 返回的数据是个字典:有refresh access
"""
old_data = super ( ) . validate( attrs)
data = { 'code' : 100 ,
'msg' : '登录成功' ,
'username' : self. user. username,
'refresh' : old_data. get( 'refresh' ) ,
'token' : old_data. get( 'access' ) ,
}
return data
【2 】 配置文件配置:
SIMPLE_JWT= {
"TOKEN_OBTAIN_SERIALIZER" : "aoo01.serialzier.MyTokenObtainPairSerializer" ,
}
import base64
res = base64. b64decode( "eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNzIyNzU1ODY4LCJpYXQiOjE3MjI3NTIyNjgsImp0aSI6ImUyNDExNGU1OWFhZjQ3MjJhNTRiNGIxYmFlNGIxMGNiIiwidXNlcl9pZCI6MSwibmFtZSI6Inp5YiIsImVtYWlsIjoiODhAcXEuY29tIn0=" )
print ( res)
Ⅳ 多方式登录
【一】关于迁移文件和扩写表字段
【1】扩写表字段迁移会报错
- 配置文件配置:
AUTH_USER_MODEL= 'aoo01.UserInfo'
-
如果要扩写auth的user表- - > 必须在没迁移之前就扩写
一旦迁移之后,再扩写就会出问题- - > 尽量不要这样做
- 真的没办法了- - 尽量少用:毕竟是无法撤回的操作
1 删库- - - > (保存之前库的数据)
2 删除迁移文件
自己app的
django内置app的 admin 和auth
【2】删除迁移文件步骤
(1)先删库
(2)删除迁移文件
(3)删除django内置的
把源码admin下得migrations里面的迁移文件删除
【二】关于多方式登录
【1】扩写字段
from django. db import models
from django. contrib. auth. models import AbstractUser
class UserInfo ( AbstractUser) :
mobile = models. CharField( max_length= 11 , default= True )
AUTH_USER_MODEL= 'aoo01.UserInfo'
【2】关于多方式登录介绍
用户名+ 密码
手机号+ 密码
邮箱+ 密码
{ username: 'zyb/15036883311/88@qq.com' , password: '741' }
【三】代码实现
from django. shortcuts import render
from rest_framework. views import APIView
from rest_framework. response import Response
from rest_framework_simplejwt. authentication import JWTTokenUserAuthentication
from rest_framework. permissions import IsAuthenticated
class BookView ( APIView) :
authentication_classes = [ JWTTokenUserAuthentication]
permission_classes = [ IsAuthenticated]
def get ( self, request) :
return Response( "很多玉树" )
from . serialzier import LoginSerialzier
class LoginView ( APIView) :
def post ( self, request) :
'''1 都写在视图类的方法中
1 取出用户名,密码
2 去数据库校验
3 校验通过,签发token
4 不通过返回错误信息
'''
'''2 换种思路
1 实例化得到序列化类对象
2 序列化类对象调用-->is_valid--->走字段自己,局部钩子,全局钩子校验
-全局钩子中:取出用户名,密码-->去数据库校验-->校验通过,签发token
3 is_valid通过,继续往下走,取出token
4 返回登录成功信息
'''
serializer = LoginSerialzier( data= request. data)
serializer. is_valid( raise_exception= True )
refresh = serializer. context. get( 'refresh' )
access = serializer. context. get( 'access' )
return Response( { 'code' : 100 , 'msg' : '登录成功' , 'refresh' : refresh, 'access' : access} )
from rest_framework_simplejwt. serializers import TokenObtainPairSerializer
from rest_framework_simplejwt. views import TokenObtainPairView
class MyTokenObtainPairSerializer ( TokenObtainPairSerializer) :
@classmethod
def get_token ( cls, user) :
token = super ( ) . get_token( user)
token[ 'name' ] = user. username
return token
def validate ( self, attrs) :
"""
自定义返回的格式
self.user 就是当前登录用户
super().validate(attrs) 返回的数据是个字典:有refresh access
"""
old_data = super ( ) . validate( attrs)
data = { 'code' : 100 ,
'msg' : '登录成功' ,
'username' : self. user. username,
'refresh' : old_data. get( 'refresh' ) ,
'token' : old_data. get( 'access' ) ,
}
return data
from rest_framework import serializers
from . models import UserInfo
from rest_framework_simplejwt. tokens import RefreshToken
from rest_framework. exceptions import APIException
class LoginSerialzier ( serializers. Serializer) :
username = serializers. CharField( )
password = serializers. CharField( )
def validate ( self, attrs) :
username = attrs. get( 'username' )
password = attrs. get( 'password' )
import re
if re. match ( r'^1[3-9][0-9]{9}$' , username) :
user = UserInfo. objects. filter ( mobile= username) . first( )
elif re. match ( r'^.+@.+$' , username) :
user = UserInfo. objects. filter ( email= username) . first( )
else :
user = UserInfo. objects. filter ( username= username) . first( )
if user and user. check_password( password) :
refresh = RefreshToken. for_user( user)
refresh_token = str ( refresh)
access_token = str ( refresh. access_token)
self. context[ 'refresh' ] = refresh_token
self. context[ 'access' ] = access_token
return attrs
else :
raise APIException( '用户名或密码错误' )
from django. contrib import admin
from django. urls import path, include
from aoo01. views import LoginView
from rest_framework_simplejwt. views import token_obtain_pair, token_refresh
urlpatterns = [
path( 'admin/' , admin. site. urls) ,
path( 'mul_login/' , LoginView. as_view( ) ) ,
path( 'login/' , token_obtain_pair) ,
path( 'api/v1/' , include( 'aoo01.urls' ) ) ,
path( 'refresh/' , token_refresh) ,
]
【四】总结
- 1 认证:固定的
class BookView ( APIView) :
authentication_classes = [ JWTTokenUserAuthentication]
permission_classes = [ IsAuthenticated]
- 2 签发:
- 1 使用simple- jwt提供的
- 修改返回格式
- 修改荷载
- 2 自定义 login,实现多方式登录- - > 基于auth的user表签发
- 1 认证:自定义认证类
- 2 签发:自己写
Ⅴ 自定义用户表-签发和认证
【一】签发
path( 'my_login/' , MyLoginView. as_view( ) ) ,
class User ( models. Model) :
username = models. CharField( max_length= 32 )
password = models. CharField( max_length= 32 )
age = models. CharField( max_length= 32 )
from . serialzier import MyLoginSerialzier
class MyLoginView ( GenericAPIView) :
serializer_class = MyLoginSerialzier
def post ( self, request) :
serializer = self. get_serializer( data= request. data)
serializer. is_valid( raise_exception= True )
refresh = serializer. context. get( 'refresh' )
access = serializer. context. get( 'access' )
return Response( { 'code' : 100 , 'msg' : '登录成功' , 'refresh' : refresh, 'access' : access} )
from . models import User
class MyLoginSerialzier ( serializers. Serializer) :
username = serializers. CharField( )
password = serializers. CharField( )
def validate ( self, attrs) :
username = attrs. get( 'username' )
password = attrs. get( 'password' )
user = User. objects. filter ( username= username, password= password) . first( )
assert user, APIException( '用户名密码错误' )
refresh = RefreshToken. for_user( user)
self. context[ 'refresh' ] = str ( refresh)
self. context[ 'access' ] = str ( refresh. access_token)
return attrs
from rest_framework. views import exception_handler
from rest_framework. response import Response
def common_exception_handler ( exc, context) :
response= exception_handler( exc, context)
if response:
return Response( { 'code' : 999 , 'msg' : '服务器异常,请稍后再试' } )
else :
if isinstance ( exc, AssertionError) :
return Response( { 'code' : 109 , 'msg' : str ( exc) } )
else :
return Response( { 'code' : 888 , 'msg' : '稍后再试' } )
REST_FRAMEWORK = {
'EXCEPTION_HANDLER' : 'aoo01.exception.common_exception_handler' ,
}
【二】认证
from rest_framework. authentication import BaseAuthentication
from rest_framework. exceptions import APIException
from rest_framework_simplejwt. authentication import JWTAuthentication
from . models import User
from rest_framework_simplejwt. tokens import AccessToken
class JsonWebTokenCommonAuthentication ( BaseAuthentication) :
def authenticate ( self, request) :
token= request. META. get( 'HTTP_AUTHORIZATION' )
if token:
try :
res = AccessToken( token)
except Exception:
raise APIException( 'token认证失败' )
user_id= res. get( 'user_id' )
user= User. objects. get( pk= user_id)
return user, token
else :
raise APIException( '没有携带认证信息' )
- 不需要再搭配permission了
- 放在请求头中:Authorization:adsfasfd. asdfasdf. asfdasd
class BookView ( APIView) :
authentication_classes = [ JsonWebTokenCommonAuthentication]
from . auth import JsonWebTokenCommonAuthentication
class BookView ( APIView) :
authentication_classes = [ JsonWebTokenCommonAuthentication]
def get ( self, request) :
return Response( '哈哈哈哈哈好吧' )
Ⅵ 权限介绍
- 访问控制列表:ACL- - > 针对于互联网用户
- 抖音:评论,点赞,开直播
张三用户: [ 评论,点赞]
李四用户: [ 评论,点赞, 开直播]
- RBAC 基于角色的访问控制- - > 公司内部
- 开发部:张三 李四
[ 删除代码,查看代码]
- 运维部:王五
[ 操作服务器]
- 总裁办: lqz
[ 发工资]
- ABAC:基于属性的访问控制- - > 在rbac基础上扩展
RBAC 是基于角色的访问控制(Role- Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY