django-restframework-simplejwt使用
安装
pip install djangorestframework_simplejwt
设置
在settings.py中 ```python
drf配置
REST_FRAMEWORK = {
# JWT'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_simplejwt.authentication.JWTAuthentication',),
}
JWT配置 里面具体配置可以参考文档
SIMPLE_JWT = { ‘ACCESS_TOKEN_LIFETIME’: timedelta(days=7), # 配置过期时间 ‘REFRESH_TOKEN_LIFETIME’: timedelta(days=15), }
> 在主目录下面的urls.py> ```python"""djangoProject15 URL ConfigurationThe `urlpatterns` list routes URLs to views. For more information please see:https://docs.djangoproject.com/en/3.1/topics/http/urls/Examples:Function views1. Add an import: from my_app import views2. Add a URL to urlpatterns: path('', views.home, name='home')Class-based views1. Add an import: from other_app.views import Home2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')Including another URLconf1. Import the include() function: from django.urls import include, path2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))"""from django.contrib import adminfrom django.urls import path, includefrom rest_framework_simplejwt.views import (TokenObtainPairView, TokenRefreshView)urlpatterns = [path('admin/', admin.site.urls),path('token/', TokenObtainPairView.as_view(), name='token_obtain_pair'),path('token/refresh/', TokenRefreshView.as_view(), name='token_refresh'),]
得到token数据返回
refresh书用来刷新的
access是token
{"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYxMTQ4ODk4MywianRpIjoiZWYyMDE1YzMwYzkwNGZlZjg0ZDNmM2ZiMmFiMDBmZDgiLCJ1c2VyX2lkIjozfQ.6fy8Dz6KDiBdTKBVAhjwi1jputZixD3yEJsFOY9JRFE","access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjEyMDA3MzgzLCJqdGkiOiI1ZDVhZTM5MTY2ZTk0NDYwYmFhYTRlODE5NTAyYmY1ZiIsInVzZXJfaWQiOjN9.seodK-XcsbgZ5AgwONxGzlDAFY3v5THQyiU-h7c-DE8"}刷新得到的数据
{"access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNTg1NjIxNTIyLCJqdGkiOiI4MzcyN2UwYWVhMDU0MWYyYmE1ODljOWY5NTMzYjE2OSIsInVzZXJfaWQiOjF9.NTo1YKFl9tvcCYQVmBWLz0rhRL8044qT65jbe7okeG0"}
自定义djangorestframework-simplejwt
在你的serializers.py ```python from rest_framework_simplejwt.serializers import TokenObtainPairSerializer
class MyTokenObtainPairSerializer(TokenObtainPairSerializer):
'''token验证'''def validate(self, attrs):data = super().validate(attrs)refresh = self.get_token(self.user)data['refresh'] = str(refresh)data['access'] = str(refresh.access_token)data['username'] = self.user.username #这个是你的自定义返回的data['user_id'] = self.user.id #这个是你的自定义返回的return data
> 在你的views.py> ```pythonfrom rest_framework_simplejwt.views import TokenViewBasefrom rest_framework_simplejwt.serializers import TokenRefreshSerializerfrom .serializers import *from .models import *class MyTokenObtainPairView(TokenObtainPairView):"""自定义得到token username: 账号或者密码 password: 密码或者验证码"""serializer_class = MyTokenObtainPairSerializerclass MyTokenRefreshView(TokenViewBase):"""自定义刷新token refresh: 刷新token的元素"""serializer_class = TokenRefreshSerializer
在你的url.py中ur
urlpatterns = ["""其他路由"""path('token/', MyTokenObtainPairView.as_view(), name='token_obtain_pair'),path('token/refresh/', MyTokenRefreshView.as_view(), name='token_refresh'),]得到token ```json
{ “refresh”: “eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYxMTQ4OTQ0MiwianRpIjoiNGE4NjkwZDQ0MTVlNDBlNzkxMThhOGYzZTUyODdlYzAiLCJ1c2VyX2lkIjozfQ.DaCk2ADDDgof4l8goL4PZkDAVpGHcplYCry8mFI452M”, “access”: “eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjEyMDA3ODQyLCJqdGkiOiJkZjY2MGE3MWRmZmU0MGFlYjRkMzRmOTNjYzk0NThkNSIsInVzZXJfaWQiOjN9.boLQPtnnW10EVN2lUon6AG0N537E6Y5eadx5ttqnysg”, “username”: “admins”, “user_id”: 3 }
> 刷新token> ```json{"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoicmVmcmVzaCIsImV4cCI6MTYxMTQ4OTY2NiwianRpIjoiODgxNGE3M2YyNGY1NGM0ZGIyZjVlNGFiMGRiNmI2ZTIiLCJ1c2VyX2lkIjozfQ.LhlzCuxLdzwWq14V1Bu7pd19VZnIGCZHd1Cl3_6hNiI","access": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJ0b2tlbl90eXBlIjoiYWNjZXNzIiwiZXhwIjoxNjEyMDA4MDY2LCJqdGkiOiJlMzY2ZWJkOWVhYTA0NGI0YjZjMTk2N2RjM2U1MGRlOCIsInVzZXJfaWQiOjN9.VM2iMCB7GSi563np-kFdsgZ5337cLiHHE4p96n8G7dA","username": "admins","user_id": 3}
接口验证
在你的views.py中 ```python class UserViewSet(CacheResponseMixin, viewsets.ModelViewSet): “”” 测试的Api1 “”” permission_classes = [permissions.IsAuthenticated] # 权限认证主要是这个 queryset = User.objects.all() serializer_class = UserSerializer throttle_classes = []
# 自定义分页pagination_class = LisPagination
> 错误返回> ```json{"msg": "身份认证信息未提供。","state": 0,"data": ""}
这个token是加在请求头的Authorization
太长就截图看了太长就截图看了
![]()
现在自定义token接口完成了
但是drf jwt默认验证的是username和password
突然想验证手机号码或者其他什么的只是自定义了
PS:本来想换请求数据中的key的、就是不要username、password。因为能力有限暂时不知道怎么换。看了好久源码好像是和Django user模型绑定了在settings.py中
pine_mountain_bridge里面的utils新建CustomToken.py
# 自定义JWT校验AUTHENTICATION_BACKENDS = ('pine_mountain_bridge.utils.CustomToken.CustomBackend',)
CustomToken.py
# 自定义得到token校验from django.contrib.auth.backends import ModelBackendfrom django.db.models import Qfrom rest_framework import serializersfrom users.models import *class CustomBackend(ModelBackend):def authenticate(self, request, username=None, password=None, **kwargs):# print(request.data) 参考请求的其他数据# print(request.data['demo']) 比如说key是demo的数据用来做你要的数据校验try:# 小编这里添加了一个手机验证,如果需要其他验证再加就ok了try:user = Users.objects.get(Q(username=username) | Q(mobile=username))except Exception:raise serializers.ValidationError({'': '账号没有注册'})if user.check_password(password):return userelse:# 如果不想密码登录也可以验证码在这里写# 这里做验证码的操作raise serializers.ValidationError({'': '密码错误'})except Exception as e:raise e
返回数据

截屏2020-03-24上午10.45.40.png
jwt解码
根据token返回对于的数据
在你的serializers.py
from rest_framework_simplejwt.serializers import TokenVerifySerializerfrom jwt import decode as jwt_decodeclass MyTokenVerifySerializer(TokenVerifySerializer):"""token验证"""def validate(self, attrs):"""attrs['token']: 是请求的tokensettings.SECRET_KEY: setting.py默认的key 除非在配置文件中修改了algorithms: 加密的方法"""decoded_data = jwt_decode(attrs['token'], settings.SECRET_KEY, algorithms=["HS256"])return decoded_data
在views.py
from rest_framework_simplejwt.views import TokenObtainPairView, TokenViewBaseclass MyTokenVerifyView(TokenViewBase):"""验证token得到用户信息 token: 验证的token"""serializer_class = MyTokenVerifySerializer
返回的数据
user_id就是你的用户ID
{"msg": "success","status": 200,"data": {"token_type": "access","exp": 1585710741,"jti": "97b42a6570d84108bf09701a60fbf5c1","user_id": 1}}
djangorestframework-simplejwt退出登录
JWT是不带退出内置的办法的
JWT退出登录很多方法
我这里是使用Django-redis库、用redis管理JWT的状态。用用户作为key保存token。
因为每个人的业务逻辑不一样、我就贴一些关键的代码在setting.py
# redis配置CACHES = {"default": {"BACKEND": "django_redis.cache.RedisCache","LOCATION": "redis://127.0.0.1:6379","OPTIONS": {"CLIENT_CLASS": "django_redis.client.DefaultClient","PASSWORD": "",}}}# redis缓存时间REDIS_TIMEOUT = 60*60*24*7
使用
from django.core.cache import cache
保存redis缓存
# 设置redis缓存# redis_key你的key# token token# REDIS_TIMEOUT 保存的数据cache.set(redis_key, token, REDIS_TIMEOUT)
清除redis缓存
我这里是把value变成空了、方便我判断
# 设置redis缓存# redis_key你的key# REDIS_TIMEOUT 保存的数据cache.set(redis_key,'', REDIS_TIMEOUT)
查看redis缓存
# 解码token得到user_iddecoded_data = jwt_decode(token algorithms=["HS256"])# redis_key 你设置的redis的keyresults = cache.get(redis_key)# 判断、写自己的业务逻辑

