Django Rest Framework 源码解析--认证
接上一篇文章;restframework重写的dispatch()方法中,执行了inital()函数。其中perform_authentication(request) 方法实现了请求的认证功能。
1、perform_authentication()函数中执行了Request类(rest_framework.reqeust.py中定义的类)的对象request(新封装的request)的user方法
def perform_authentication(self, request):
"""
Perform authentication on the incoming request.
Note that if you override this and simply 'pass', then authentication
will instead be performed lazily, the first time either
`request.user` or `request.auth` is accessed.
"""
# 执行新封装的request对象的的user方法(是个property所以不用user() )
request.user
2、经过一些判断之后,跳转到** _authenticate()** 方法
class Request(object):
"""
Wrapper allowing to enhance a standard `HttpRequest` instance.
Kwargs:
- request(HttpRequest). The original request instance.
- parsers_classes(list/tuple). The parsers to use for parsing the
request content.
- authentication_classes(list/tuple). The authentications used to try
authenticating the request's user.
"""
......
@property
def user(self):
"""
Returns the user associated with the current request, as authenticated
by the authentication classes provided to the request.
"""
if not hasattr(self, '_user'):
with wrap_attributeerrors():
self._authenticate()
return self._user
3、在Request类的_authenticate()方法中,执行** authenticators**(认证对象列表) 中的每一个认证对象的 **authenticate() **方法。
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
# 获取每一个认证对象实例
for authenticator in self.authenticators:
try:
# 使用认证对象的authenticate()方法
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
# 如果认证对象没有写authenticate()方法,抛出异常_not_authenticated()
self._not_authenticated()
raise
# 如果写了authenticate()方法,并且执行后返回的不是None
# 则给request对象实例生成3个成员 self._authenticator, self.user, self.auth
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return
# 如果执行authenticate()方法之后返回的是None
# 则继续循环,执行对象列表中下一个 认证对象的方法,直到最后一个对象
self._not_authenticated()
# authenticate()的返回值应该是(should be)一个元祖,元祖的值 (self.force_user, self.force_token)
# 返回的值是最终通过认证的用户和token,这些会作为成员变量赋值给request,可以在view中调用self.user, self.auth
def authenticate(self, request):
return (self.force_user, self.force_token)
使用示例:
1、自定义一个认证类,继承BaseAuthentication类
class MyAuthentication(BaseAuthentication):
'''用于用户登录验证'''
def authenticate(self,request):
token = request._request.GET.get('token')
# UserToken自定义的存储token的表与用户表一对一关系
token_obj = models.UserToken.objects.filter(token=token).first()
if not token_obj:
raise exceptions.AuthenticationFailed('用户认证失败')
#在rest framework内部会将这两个字段赋值给request,以供后续操作使用
return (token_obj.user,token_obj)
2、想要调用认证类有两种方法
①在全局的setting.py文件中设置认证类的路径
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": (
'restframework_class.auth.MyAuthentication',
)
}
②在View中重写authentication_classes列表,调用认证类
class TestView(APIView):
# 重点看这一行,重写authentication_classes列表,调用认证类
# 自定义的类MyAuthentication此时是最后一个认证类,所以必须返回(user, token)
authentication_classes = (MyAuthentication, )
def get(self,request,*args,**kwargs):
pass
网友评论