DRF 认证(2)
self.initial()
这里的request 是封装后的request,传入def initial(self, request, *args, **kwargs)这个方法
def initial(self, request, *args, **kwargs):
"""
Runs anything that needs to occur prior to calling the method handler.
"""
self.format_kwarg = self.get_format_suffix(**kwargs)
# Perform content negotiation and store the accepted info on the request
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
# Determine the API version, if versioning is in use.
version, scheme = self.determine_version(request, *args, **kwargs)
request.version, request.versioning_scheme = version, scheme
# Ensure that the incoming request is permitted
# 身份认证
self.perform_authentication(request)
# 检查权限
self.check_permissions(request)
# 流量限速
self.check_throttles(request)
self.perform_authentication(request)
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
他返回的是新封装request的user属性。那我们就得看下他源码是如何封装这个属性,以及user这个属性表示什么
@property
def user(self):
"""
Returns the user associated with the current request, as authenticated
by the authentication classes provided to the request.
返回与当前请求关联的经过身份验证的用户,提供给请求的身份验证
"""
# 判断如果_user 不在request中的话,执行 self._authenticate()这个方法
if not hasattr(self, '_user'):
with wrap_attributeerrors():
# 执行认证方法
self._authenticate()
return self._user
我们可以看到他其实还是执行了self._authenticate()。我们还是要看下他的这个authenticate()方法。
self._authenticate()
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
for authenticator in self.authenticators:
try:
# 执行认证类的authenticate方法
# 这里分三种情况
# 1.如果authenticate方法抛出异常,self._not_authenticated()执行
# 2.有返回值,必须是元组:(request.user,request.auth)
# 认证类的实例执行authenticate()这个方法,这个可以重写自己的代码逻辑
user_auth_tuple = authenticator.authenticate(self)
except exceptions.APIException:
self._not_authenticated()
raise
# 3.返回None,表示当前认证不处理,等下一个认证来处理
if user_auth_tuple is not None:
self._authenticator = authenticator
# 返回值对应示例中的token_obj.user和token_obj
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()
小结
- 这里他将执行每一个认证类的实例的authenticate()方法,也就是说如果要写认证类的话是必须写这个方法的
- 必须要求返回元祖,然后元祖不为空时就将元祖内的user赋值给self.user,其实也就是侧面赋值给了self._user,
返回到self.perform_authentication(request)这里,其实也就是返回了这个self._user,使得我们认证知道请求是谁,是否登录的作用
def authenticate(self, request)
class ForcedAuthentication:
"""
This authentication class is used if the test client or request factory
forcibly authenticated the request.
"""
def __init__(self, force_user, force_token):
self.force_user = force_user
self.force_token = force_token
# 一定返回元组
def authenticate(self, request):
return (self.force_user, self.force_token)
这个认证工厂要求必须返回元祖
def _not_authenticated(self)
def _not_authenticated(self):
"""
Set authenticator, user & authtoken representing an unauthenticated request.
Defaults are None, AnonymousUser & None.
"""
self._authenticator = None
if api_settings.UNAUTHENTICATED_USER:
self.user = api_settings.UNAUTHENTICATED_USER()
else:
self.user = None
if api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN()
else:
self.auth = None
小结
没有身份,相当于匿名用户,默认设置AnonymousUser,如需要单独设置匿名用户返回值,
则编写需要写UNAUTHENTICATED_USER的返回值
所以我们需要认证的时候,需要在每一个认证类中定义authenticate进行验证,并且需要返回元祖
配置认证类
我们知道全局配置都在api_setting中
其中引用了django,settings.py中的REST_FRAMEWORK作为key作为配置,所以全局配置示例:
#全局认证配置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',] #其中写认证的类的路径,不要在views中,这里我放在了utils目录下auth.py中
}
局部使用
局部某个视图不需要认证,则在视图类中加入authentication_classes=[]
authentication_classes = [] #authentication_classes为空,代表不需要认证
匿名设置
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',], #其中写认证的类的路径,不要在views中,这里我放在了utils目录下auth.py中
"UNAUTHENTICATED_USER": lambda:"匿名",#匿名用户配置,只需要函数或类的对应的返回值,对应request.user="匿名"
"UNAUTHENTICATED_token": None,#匿名token,只需要函数或类的对应的返回值,对应request.auth=None
}
内置认证类
BaseAuthentication
BaseAuthentication是django rest framework为我们提供了最基本的认证类,正如源码流程一样,该类中其中定义的两个方法authenticate和authenticate_header(认证失败返回的响应头),使用时候重写该两个方法进行认证,正如示例:
class BaseAuthentication(object):
"""
All authentication classes should extend BaseAuthentication.
"""
def authenticate(self, request):
"""
Authenticate the request and return a two-tuple of (user, token).
"""
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.
"""
pass```
其他认证类
```python
rest_framework.authentication
BasicAuthentication #基于浏览器进行认证
SessionAuthentication #基于django的session进行认证
RemoteUserAuthentication #基于django admin中的用户进行认证,这也是官网的示例
TokenAuthentication #基于drf内部的token认证
自定义认证类
继承BaseAuthentication,重写authenticate方法和authenticate_header(pass就可以),authenticate()方法需要有三种情况(返回元祖、出现异常、返回none)。
认证配置
#全局认证
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES":['API.utils.auth.Authentication',]
}
#局部认证
authentication_classes = [BaseAuthentication,]
#是某个视图不进行认证
authentication_classes =[]
上一篇: 获取已关注公众号的用户的信息