03-Drf认证
使用token对用户的访问进行认证,认证不通过的用户返回非法提示
编写登录视图
drf_auth.viewss.py
class Login(APIView): def post(self, request): # 响应的字典 response = dict() fields = {'username', 'password'} user_info = dict() if fields.issubset(set(request.data)): for key in fields: user_info[key] = request.data[key] # 使用Django认证组件进行校验 user_instance = authenticate(**user_info) # 校验成功 if user_instance is not None: # 生成token access_token = generate_token() # 更新或创建Token UserToken.objects.update_or_create(user=user_instance, defaults={'token': access_token}) response['status_code'] = 200 response['status_message'] = '登录成功' response['access_token'] = access_token response['user_role'] = user_instance.get_user_level_display() else: # 校验失败 response['status_code'] = 201 response['status_message'] = '用户名或密码错误' return Response(response)
postman测试登录

根据规则,没有登录用户,无权限访问books路由
定义认证类
from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import APIException # 自定义认证类,需要重写authenticate方法,该方法里写认证逻辑代码,认证失败抛出APIException异常 class UserAuth(BaseAuthentication): def authenticate(self, request): user_token = request.query_params.get('token') try: token = UserToken.objects.get(token=user_token)
#在rest framework内部会将这两个字段赋值给request,以供后续操作使用
return token.user, token.token except Exception as e: raise APIException('非法访问用户')
使用认证类
全局配置
REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ['utils.auth_component.UserAuth'], }
登录和注册不需要认证,其他所有页面都需要登录后才能访问,我们用postman发送请求测试下
class Login(APIView): authentication_classes = [] ..... class Reg(APIView): authentication_classes = [] ....

登录无认证限制

其他路由,非认证用户限制访问

带token用户,正常访问。
局部配置
根据业务场景来看,部分路由只能登录用户访问,这时就不用配置全局,对单独视图类进行配置
from utils.auth_component import UserAuth class BookView(ModelViewSet):
# 认证 authentication_classes = [UserAuth] queryset = Book.objects.all() serializer_class = BookSerialize
BaseAuthentication源码
class BaseAuthentication(object): """ All authentication classes should extend BaseAuthentication. """ def authenticate(self, request): """ Authenticate the request and return a two-tuple of (user, token). """ #内置的认证类,authenticate方法,如果不自己写,默认则抛出异常 raise NotImplementedError(".authenticate() must be overridden.") def authenticate_header(self, request): """ Return a string to be used as the value of the `WWW-Authenticate` header in a `401 Unauthenticated` response, or `None` if the authentication scheme should return `403 Permission Denied` responses. """ #authenticate_header方法,作用是当认证失败的时候,返回的响应头 pass
其它内置认证类
rest_framework里面还内置了其它认证类,我们主要用到的就是BaseAuthentication,剩下的很少用到

总结
自己写认证类方法梳理
(1)创建认证类
- 继承BaseAuthentication --->>1.重写authenticate方法;2.authenticate_header方法直接写pass就可以(这个方法必须写)
(2)authenticate()返回值(三种)
- None ----->>>当前认证不管,等下一个认证来执行
- raise exceptions.AuthenticationFailed('用户认证失败') # from rest_framework import exceptions
- 有返回值元祖形式:(元素1,元素2) #元素1复制给request.user; 元素2复制给request.auth
(3)局部使用
- authentication_classes = [BaseAuthentication,]
(4)全局使用
#设置全局认证
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ['utils.auth_component.UserAuth'],
}
源码流程
--->>dispatch
--封装request
---获取定义的认证类(全局/局部),通过列表生成式创建对象
---initial
----peform_authentication
-----request.user (每部循环创建的对象)
浙公网安备 33010602011771号