drf-jwt第三方插件,DRF的三大认证的具体使用,多方式登陆的实现
Posted mcoming
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了drf-jwt第三方插件,DRF的三大认证的具体使用,多方式登陆的实现相关的知识,希望对你有一定的参考价值。
[TOC]
一、 JWT认证的使用
1. 第三方drf-jwt
插件
借助第三方的
drf-jwt
插件,进行jwt认证,完成token的签发和校验和刷新(需要先手动下载,命令是:pip install djangorestframework-jwt
)drf-jwt
插件其实就是一个小的应用,包含了settings,views,utils,serializers,models
等文件。有关token的配置参数就在插件的settings文件中,我们也可以在自己项目的settings文件中配置后,然后覆盖掉插件中的默认配置,达到自定义token配置的目的。
-
项目的settings文件中,当然还可以配置token的其他参数 # drf-jwt自定义配置 import datetime JWT_AUTH = { # 过期时间 ‘JWT_EXPIRATION_DELTA‘: datetime.timedelta(seconds=300), # 是否允许刷新 ‘JWT_ALLOW_REFRESH‘: False, # 最大刷新的过期时间 ‘JWT_REFRESH_EXPIRATION_DELTA‘: datetime.timedelta(days=7), }
-
注意:在token的签发中,有两个方法很重要
*****jwt_payload_handler和jwt_encode_handler方法*****
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
# 1. 用user对象包装成payload载荷
payload = jwt_payload_handler(user)
# 2. 利用payload载荷签发token(jwt认证的头部在系统内部已写死,不需要我们参与编写了)
token = jwt_encode_handler(payload)
2. 利用第三方插件的views完成token操作
1. 应用的urls文件中:
from django.conf.urls import url, include
from .router import router
# eg: router.register(‘users‘, UserModelViewSet, basename=‘user‘)
from rest_framework_jwt.views import ObtainJSONWebToken, obtain_jwt_token, refresh_jwt_token, verify_jwt_token
urlpatterns = [
# ObtainJSONWebToken.as_view()等价于obtain_jwt_token
# url(r‘^login/$‘, ObtainJSONWebToken.as_view()),
url(r‘^login/$‘, obtain_jwt_token), # 登录接口(签发token)
url(r‘^refresh/$‘, refresh_jwt_token), # 刷新token接口
url(r‘^verify/$‘, verify_jwt_token), # 校验token接口
url(r‘‘, include(router.urls))
]
二、DRF的三大认证的使用
三大认证组件:认证组件、权限组件、频率组件
- 认证组件:身份认证(游客/合法用户/非法用户)
- 权限组件:针对游客和合法用户对某一视图函数的访问权限
- 频率组件:限制某一视图函数在一定时间内被访问的次数
三大组件是按流水线式轮流进行,即:先进行认证——》再权限校验——》最后是频率校验
借助第三方的
drf-jwt
插件,进行jwt认证,完成token的签发和校验和刷新(需要先手动下载,命令是:pip install djangorestframework-jwt
)-
drf-jwt插件: 提供了 签发token、校验token、刷新token的三个视图类 认证组件中(校验jwt token,得到登录用户user对象,存储到request.user中)
-
在视图类的自身逻辑之前书写需要的三大认证功能(注意是之前),即在视图类的下面的第一行书写三大认证。
三、认证组件的使用
1. 认证组件的用法和注意点
实际开发中对DRF自带的认证功能需求大,且一般在全局中配置认证组件。
自定义的认证功能在实际开发中需求较少,但也可能会出现。
注意:登录接口不用参与任何认证与权限的校验
在认证功能中,认证类返回值有以下3中情况
-
1. 没有token或者前台提交的token格式错误 返回 None 表示游客 2. 有正常的token token校验不通过,则抛出AuthenticationFailed异常,代表非法用户 3. 有正常的token token校验通过,返回 (user,token) ,表示合法用户(user是用户对象)
-
2. 认证组件使用步骤
(1)使用DRF自带的认证功能(非登陆功能中)
- 使用步骤:
1. 在settings文件中配置drf框架的认证组件
REST_FRAMEWORK = {
# 异常模块:异常处理函数
‘EXCEPTION_HANDLER‘: ‘api.exception.exception_handler‘,
# 配置全局认证组件
‘DEFAULT_AUTHENTICATION_CLASSES‘: [
‘rest_framework_jwt.authentication.JSONWebTokenAuthentication‘
],
# 频率组件:频率类一般做局部配置,但是频率调节在settings中配置
‘DEFAULT_THROTTLE_RATES‘: {
‘user‘: ‘5/min‘,
‘anon‘: ‘3/min‘,
‘mobile‘: ‘1/min‘
},
}
2. 书写视图类的正常逻辑代码
(2)使用自定义的认证类(非登录功能中)
- 使用步骤:
# 这里自定义的认证类是在局部配置的,但一般是在settings文夹中进行全局配置
1. 在应用文件夹下新建文夹,书写自定义的认证类
如: 新建 authentications.py文夹,内部定义继承了BaseAuthentication类的MyAuthentication类
2. 在视图类的正常逻辑代码之前进行认证类的配置
from . import authentications
authentication_classes = [authentications.MyAuthentication]
3. 书写视图类的正常逻辑代码
(3)自定义认证类实例
‘‘‘
自定义认证类
1) 如果使用session认证,drf默认提供了SessionAuthentication
2) 如果使用drf-jwt认证框架,drf-jwt框架提供了JSONWebTokenAuthentication
3) 如果是自定义签发与校验token,才需要将校验token的算法封装到自定义的认证类中
‘‘‘
from rest_framework.authentication import BaseAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
class MyAuthentication(BaseAuthentication):
def authenticate(self, request):
"""
1) 从请求头中拿到前台提交的token(一般从HTTP_AUTHORIZATION中拿,也可以与前台约定)
-- 如果设置了反爬等措施,校验一下反爬(头 token)
2)没有token,返回None,代表游客
3)有token,进入校验
-- 不通过:抛AuthenticationFailed异常,代表非法用户
-- 通过:返回 (user, token),代表合法用户
"""
pass
四、权限组件的使用
1. 权限组件的用法和注意点
权限校验一般进行局部配置,因为不同的用户对视图类的权限差别很大,所以要分别配置(当然也可以同时进行全局配置和局部配置)
在实际开发中,DRF自带的权限组件功能和自定义权限类两者都会有需求
注意:登录接口不用参与任何认证与权限的校验
权限类的返回值有两种情况
-
1. 返回 True # 条件通过,即有权限 2. 返回 False # 条件不通过,即没有权限
-
2. 权限组件使用步骤
(1)使用DRF自带的权限功能(非登录功能中)
- 使用步骤
1. 视图类中进行局部配置DRF自带的权限组件
from rest_framework.permissions import IsAuthenticated, IsAdminUser, AllowAny, IsAuthenticatedOrReadOnly
permission_classes = [IsAuthenticated]
permission_classes = [IsAdminUser]
2. 书写视图类的正常逻辑代码
(2)使用自定义的权限类
1. 在应用文件夹下新建一个文件,来自定义权限类
如:新建permissions.py文件,内部定义继承了BasePermission类的MyPermission类
2. 视图类中进行局部配置自定义的权限组件
from . import permissions
permission_classes = [permissions.MyPermission]
3. 书写视图类的正常逻辑代码
(3)自定义权限类实例
"""
自定义权限类
1) drf默认提供了一些权限类
AllowAny:游客和登录用户有全权限
IsAuthenticated:只有登录用户有全权限
IsAdminUser:只有后台用户(admin用户)有全权限
IsAuthenticatedOrReadOnly:游客有读权限,登录用户有全权限
2)如果有特殊需要,需要自定义权限类
如:只有superuser有权限、只有vip用户有权限、只有某ip网段用户有权限、只有某个视图及其子类有权限
"""
from rest_framework.permissions import BasePermission
class MyPermission(BasePermission):
def has_permission(self, request, view):
"""
1) 根据需求,request和view的辅助,制定权限规则判断条件
2)如果条件通过,返回True
3)如果条件不通过,返回False
"""
print(request.user, request.auth)
return False
# VIP用户权限
class VIPUserPermission(BasePermission):
def has_permission(self, request, view):
for group in request.user.groups.all():
if group.name.lower() == ‘vip‘:
return True
return False
五、频率组件的使用
1. 频率组件的用法和注意点
DRF自带的频率组件只有频率限制的条件,需要我们自己实现限制功能。
频率组件都需要我们自定义频率类,因此需求很大
频率校验一般做局部配置,但是频率校验的限制条件在settings中配置
频率类的返回值有两种
-
1. 返回 None # 表示不限制 2. 返回与限制条件有关的字符串,表示限制(注意此处的返回值的写法)
-
2. 频率组件使用步骤
- 直接就是使用自定义的频率类
1. 在应用文件夹下新建一个文件,来自定义频率类
如:新建一个throttles.py文件,其内部定义一个继承了SimpleRateThrottle类的MobileRateThrottle类
2. 在settings文件中配置频率限制条件
# drf框架自定义配置
REST_FRAMEWORK = {
# 频率组件:频率类一般做局部配置,但是频率调节在settings中配置
‘DEFAULT_THROTTLE_RATES‘: {
‘user‘: ‘5/min‘,
‘anon‘: ‘3/min‘,
‘mobile‘: ‘1/min‘
},
}
3. 在视图类中进行局部配置频率校验
from . import throttles
throttle_classes = [throttles.MobileRateThrottle]
4. 书写视图类的正常逻辑代码
(2)自定义频率类实例
"""
自定义频率类
1) drf默认提供了一些频率类
AnonRateThrottle:只对游客进行频率限制
UserRateThrottle:对所有用户进行频率限制
2)如果有特殊需要,需要自定义频率类
如:对ip进行限次、对电话进行限制、对视图某些信息进行限次
"""
from rest_framework.throttling import SimpleRateThrottle
class MobileRateThrottle(SimpleRateThrottle):
"""
1)设置scope字符串类属性,同时在settings中进行drf配置DEFAULT_THROTTLE_RATES
eg: DEFAULT_THROTTLE_RATES = {‘mobile‘: ‘1/min‘}
2)重写get_catch_key方法:
返回与限制条件有关的字符串,表示限制
返回None,表示不限制
"""
scope = ‘mobile‘
def get_cache_key(self, request, view):
if not request.user.is_authenticated or not request.user.mobile:
return None # 匿名用户 或 没有电话号的用户 都不限制
# 只要有电话号的用户才进行限制
return self.cache_format % {
‘scope‘: self.scope,
‘ident‘: request.user.mobile
}
六、多方式登陆的实现
- 实现用户名、邮箱、电话号码三种方式的登陆
- 同时实现登陆功能的
jwt认证的 token的签发
1. 登陆功能中的注意点
- token只能由登陆接口签发
- 登陆接口也是APIView的子类,使用就一定会进行认证、权限的校验,但是实际上,登陆接口不能参与任何认证和权限的校验,所以要进行认证和权限校验的局部禁用。
- 登陆所需的数据和登陆校验以及token的签发都是通过序列化类完成的。
- 注意:因为登陆是需要用户提交数据的,所以走得是post请求。但是当走post请求时,系统会默认当前要进行的是增功能。因此,我们在序列化类中,要把系统字段改为同名的自定义反序列化字段。
- 在进行token的签发时,需要用到
drf-jwt
插件来完成
2. 多方式登陆的实现代码
1. 应用的urls文件中:
from django.conf.urls import url, include
from . import views
from .router import router
router.register(‘users‘, views.UserListViewSet, basename=‘user‘) # basename就是别名
urlpatterns = [
# 自定义签发token的登录login接口
url(r‘^login/$‘, views.LoginAPIView.as_view()),
url(r‘‘, include(router.urls))
]
2. 自定义的序列化文件中:
# 登陆视图类对应的序列化类
# 导入drf-jwt插件,利用其中的两个方法完成token的签发
from rest_framework_jwt.serializers import jwt_payload_handler, jwt_encode_handler
import re
class LoginModelSerializer(serializers.ModelSerializer):
# post请求,序列化默认当做create动作进行校验,需要校验数据库,执行create动作,username会抛用户已存在异常
# 抛用户已存在异常是多余的,所以自定义系统校验规则即可,即自定义反序列化的同名字段即可
username = serializers.CharField(min_length=3, max_length=16)
password = serializers.CharField(min_length=3, max_length=16)
class Meta:
model = models.User
fields = (‘username‘, ‘password‘)
# 用全局钩子,完成token的签发
def validate(self, attrs):
# 1)通过 username 和 password 完成多方式登录校验,得到user对象
user = self._validate_user(attrs) # 自定义方法得到user对象
# 2)用user对象包装成payload载荷
payload = jwt_payload_handler(user)
# 3)利用payload载荷签发token(jwt认证的头部在系统内部已写死,不需要我们参与编写了)
token = jwt_encode_handler(payload)
# 4)将user与token存储到serializer对象中,方便在视图类中使用
self.content = {
‘user‘: user,
‘token‘: token
}
return attrs
# 利用正则,匹配出不同格式的username,再分别进行校验
def _validate_user(self, attrs):
username = attrs.get(‘username‘)
password = attrs.get(‘password‘)
if re.match(r‘.*@.*‘, username): # 邮箱
user = models.User.objects.filter(email=username).first() # type: models.User
elif re.match(r‘^1[3-9][0-9]{9}$‘, username): # 电话
user = models.User.objects.filter(mobile=username).first()
else: # 用户名
user = models.User.objects.filter(username=username).first()
if not user or not user.check_password(password):
raise serializers.ValidationError({‘message‘: ‘用户信息异常‘})
return user
以上是关于drf-jwt第三方插件,DRF的三大认证的具体使用,多方式登陆的实现的主要内容,如果未能解决你的问题,请参考以下文章