LinuxNetworkCC 2019-06-30
pip3 install djangorestframework
在dispatch中,对原生request进行了封装
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 对原生的request进行加工,包含【原生request】丰富了authenticator
request = self.initialize_request(request, *args, **kwargs)
# 获取原生的request对象 request._request
# 获取认证类对象 request.authenticators
self.request = request
self.headers = self.default_response_headers # deprecate?
try:
# 2. 认证
self.initial(request, *args, **kwargs)
.....跟进self.initial
def initial(self, request, *args, **kwargs):
self.format_kwarg = self.get_format_suffix(**kwargs)
'''版本处理'''
neg = self.perform_content_negotiation(request)
request.accepted_renderer, request.accepted_media_type = neg
......
'''进行认证'''
self.perform_authentication(request)
'''权限控制'''
self.check_permissions(request)
'''访问频率'''
self.check_throttles(request)然后继续跟进,调用了.user._authenticate()方法 # 获取认证对象进行一个一个认证,如果错误就触发异常!
这是认证和视图写在了一起,方便观看,实际中最好将认证类单独存放在一个py中from rest_framework.views import APIView
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication # 内置的认证类【必须继承】
class Authentication(BaseAuthentication): # 自己写认证,然后引用
def authenticate(self, request):
token = request._request.GET.get('token')
token_obj = models.UserToken.objects.filter(token=token).first()
if not token_obj:
# 其实在内部捕捉了异常
raise exceptions.AuthenticationFailed('用户认证失败')
# 返回user对象 + token
# 在rest framework 内部会将两个字段赋值给 request,给后面调用
'''返回值必须是元祖 第一个赋值给 request.user 第二个request.auth'''
return (token_obj.user, token_obj)
def authenticate_header(self, request):
pass
...
class DogView(APIView):
"""
应用上Authentication认证规则。如果有多个,那么依次认证
如果都没有认证,那么默认值 request.user=AnonymousUser request.auth = None 匿名用户
request.user 这是token_obj.user 源码中规定元祖第一个
request.auth 这是token_obj 源码中规定元祖第二个
"""
authentication_classes = [Authentication, ]
......
实际中将自己写的认证方法单独放在一个py中,然后在项目setting中配置即可
# 导入自己写的rest 认证路径
"""
可以局部使用或者全局使用
局部: authentication_classes = []
"""
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": ['app01.utils.auth.Authentication', ], # 全局使用的认证类,也可以局部使用
"UNAUTHENTICATED_USER": None, # 匿名用户, request.user = None
"UNAUTHENTICATED_TOKEN": None, # 匿名用户, request.auth = None
}这样写的好处是无需再视图中再写引用了,会自动按照你setting中的配置进行认证,如果指定视图不需要认证,那么在该view中写 authentication_classes = [] 即可
| 返回值 | 结果 |
|---|---|
| None | 执行下一个认证 |
| raise | 认证失败抛出异常 |
| 元祖(元素1,元素2) | 元素1=request.user; 元素2=request.auth |
全局使用
setting中配置,然后在单独的py文件中写入认证「写入路径」
局部使用
在视图中 引入authentication_classes = [认证类, ]