rest_framework 认证流程
一、基本流程
rest_framework框架是基于CBV基础开发的(VPIView(View)),所以基本流程与CBV流程相似
当我们的请求发来后,会走as_views,执行view里面的方法,最开始都要执行dispatch方法
urls.py
url(r'^books/$', views.BookViews.as_view())
views.py
class BookViews(APIView): def get(self,request,*args,**kwargs):
passdef post(self,request,*args,**kwargs):
pass
当请求进来时首先进入as_view()
APIView类中的as_view(),
进入原生View类中
所以访问views中的类是先执行dispatch方法(如果自己定义了则走自己的dispatch()),然后再用调用 其他方法
APIView中的dispatch():
二、处理认证的具体分析
当diapatch方法进行到第一步时,我们调用了initialize_request方法将request等封装在Request中顶返回其对象,
authenticators=self.get_authenticators() #用于用户认证 是一个由authentication对象组成的列表
def get_authenticators(self):
"""
Instantiates and returns the list of authenticators that this view can use.
"""
return [auth() for auth in self.authentication_classes]
authentication_classes为一个authentication类组成的列表,他默认是调用
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
当然我们一般是自己定义或者配置到settings中,至此我们的得到authentication对象的列表,其封装在Request对象中,
接的执行第二步
#2.处理版本信息 处理认证信息 处理权限信息 对用户的访问频率进行限制 self.initial(request, *args, **kwargs)
#2.2处理认证信息
self.perform_authentication(request)
查看perform_authentication的源码如下
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
其调用了rest_framework中Request的user方法(这个方法肯定别@property装饰(静态方法),不然的话不可能直接不加括号的调用)
from rest_framework.request import Request
Request类中的user方法
@property
def user(self):
"""
Returns the user associated with the current request, as authenticated
by the authentication classes provided to the request.
"""
#判断当前类中是否有已经认证过的user
if not hasattr(self, '_user'):
#没有认证则去认证
self._authenticate()
#认证过了直接返回
return self._user
注意:user中的self代表的是request对象
没认证的话执行 调用Request类中的_authenticate()方法
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
#遍历request对象中封装的Authentication对象
for authenticator in self.authenticators:
try:
#调用Authentication对象中的authenticate方法,必须要有这个方法不然抛出异常
#当然Authentication类一般有我们自己定义,实现这个方法就可以了
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise
if user_auth_tuple is not None:
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()
局部认证
auth.py
# 局部认证 from ..models import * from rest_framework.authentication import BaseAuthentication from rest_framework import exceptions class MyAuthenticate(BaseAuthentication): def authenticate(self,request): token=request._request.GET.get("token") print("token",token) user_token_obj=UserToken.objects.filter(token=token).first() if user_token_obj: # 必须返回元祖request.user=user_token_obj, request.auth=token return user_token_obj,token else: raise exceptions.AuthenticationFailed("校验失败")
view.py
class BookViewsSet(viewsets.ModelViewSet): # 认证 authentication_classes=[MyAuthenticate] queryset = Book.objects.all() serializer_class = BookModelSerializer(序列化)
全局认证
settings.py
REST_FRAMEWORK={ "DEFAULT_AUTHENTICATION_CLASSES": ["api.servise.auth.MyAuthenticate"], }
auth.py
# 局部认证
from ..models import *
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
class MyAuthenticate(BaseAuthentication):
def authenticate(self,request):
token=request._request.GET.get("token")
print("token",token)
user_token_obj=UserToken.objects.filter(token=token).first()
if user_token_obj:
# 必须返回元祖request.user=user_token_obj, request.auth=token
return user_token_obj,token
else:
raise exceptions.AuthenticationFailed("校验失败")
待续

浙公网安备 33010602011771号