DRF认证
认证的写法
# 认证的实现 1 写一个类,继承BaseAuthentication,重写authenticate,认证的逻辑写在里面, 认证通过,返回两个值,一个最终给了Request对象的user, 认证失败,抛异常:AuthenticationFailed或者APIException 2 全局使用,局部使用
认证的源码分析
# 1 APIView ---> dispatch方法 ---> self.initial(request, *args, **kwargs) ---> 有认证,权限,频率 # 2 只读认证源码: self.perform_authentication(request) # 3 self.perform_authentication(request)就一句话request.user,需要去drf的Request对象中找user属性(方法) # 4 Request类中的user方法,刚开始来,没有user,走self._authenticate() # 5 核心:就是Request类的_authenticate(self): def _authenticate(self): # 遍历拿到一个个认证器,进行认证 # self.authenticators配置的一堆认证类产生的认证类对象组成的 list # # self.authenticators 是你在视图类中配置的一个个的认证类:authentication_classes = [认证类1,认证类2...] 对象的列表 for authenticator in self.authenticators: try: # 认证器(对象)调用认证方法authenticate(认证类对象self,request请求对象) # 返回值:登录的用户与认证的信息组成的 tuple # 该方法被try包裹,代表该方法会抛异常,抛异常就代表认证失败 user_auth_tuple = authenticator.authenticate(self) # 注意这个self是request对象 except exceptions.APIException: self._not_authenticated() raise # 返回值的处理 if user_auth_tuple is not None: self._authenticator = authenticator # 如果有返回值,就将用户 与 登录认证 分别保存到 request.user request.auth self.user, self.auth = user_auth_tuple return # 如果返回值user_auth_tuple为空,代表认证通过,但是没有 登录用户 与登录认证信息,代表游客 self._not_authenticated()
认证组件的使用
# 写一个认证类 app_auth.py from rest_framework.authentication import BaseAuthentication from rest_framework.exceptions import AuthenticationFailed from app01.models import UserToken class MyAuthentication(BaseAuthentication): def authenticate(self, request): # 认证逻辑,如果认证通过,返回两个值 # 如果认证失败,抛出AuthenticationFailed异常 token = request.GET.get('token') if token: user_token = UserToken.objects.filter(token=token).first() # 认证通过 if user_token: return user_token.user,token else: raise AuthenticationFailed('认证失败') else: raise AuthenticationFailed('请求地址中需要携带token') # 可以有多个认证,从左到右依次执行 # 全局使用,在settings,py中配置 REST_FRAMEWORK = { "DEFAULT_AUTHENTICATION_CLASSES": ["app01.app_auth.MyAuthentication", ] } # 局部使用,在视图类上写: authentication_classes = [MyAuthentication] # 局部禁用 authentication_classes = []