认证组件
1、 APIview分发
继续apiview函数 进入到 dispatch方法中
def dispatch(self, request, *args, **kwargs):
# 新的request请求, initialize_request
request = self.initialize_request(request, *args, **kwargs)
2、初始化新的request
def initialize_request(self, request, *args, **kwargs):
""" Returns the initial request object. """
parser_context = self.get_parser_context(request)
return Request(
request,
parsers=self.get_parsers(),
# 认证
authenticators=self.get_authenticators(),
# 分页
negotiator=self.get_content_negotiator(),
# 解析内容
parser_context=parser_context
)
3、 进入认证组件 get_authenticators
def get_authenticators(self):
# self.authentication_classes, 这个是一个列表,用于认证组件使用
return [auth() for auth in self.authentication_classes]
# 在APIview中,api_settings 是直接从配置文件中导入的
authentication_classes = api_settings.DEFAULT_AUTHENTICATION_CLASSES
4、 当新的Request通过就继续APIview的dispatch方法
def dispatch(self):
try:
# 初始化方法
self.initial(request, *args, **kwargs)
5、 drf初始化方法
APIview下的方法
def initial(self, request, *args, **kwargs):
# 认证
self.perform_authentication(request)
# 权限
self.check_permissions(request)
# 频率
self.check_throttles(request)
6、进入到初始化认证组件中
def perform_authentication(self, request):
request.user
7、 初始化的 Request请求
# 导入,找到user这个方法
from rest_framework.request import Request
# 找到user方法, 使用了property定义成了属性
@property
def user(self):
if not hasattr(self, '_user'):
with wrap_attributeerrors():
self._authenticate()
return self._user
8、继续查找self._authenticate()
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
# 这里的self.authenticators 就是第2步的 requset中的authenticators
# return [auth() for auth in self.authentication_classes]
for authenticator in self.authenticators:
try:
# 列表中循环的就是自己定义的认证的类名
user_auth_tuple = authenticator.authenticate(self)
9、认证
# 先定义一个认证方法
import uuid
class Login(APIView):
def post(self,request, *args, **kwargs):
user = request.data.get("user")
pwd = request.data.get("pwd")
response = {"status": 100, "msg": "登陆成功"}
user_obj = models.User.objects.filter(user=user, pwd=pwd).first()
if user_obj:
token = uuid.uuid4()
models.Token.objects.create(token=token, user=user_obj)
response["token"] = token
else:
response["status"] = 101
response["msg"] = "用户名或密码错误"
return JsonResponse(response, safe=False)
# 在需要被定义认证的类下中写, 需要注意的是,这里最多只能写三个,
# 并且如果AUthUser有返回值,后面的认证组件就不会在执行
authentication_classes = [AuthUser, ]
10、AuthUser
class AuthUser():
# 这里定义第8步的 authenticator.authenticate(self),
# 类调用方法会自动传self,也就是说 这个self在定义的时候还需要手动传一个值
def authenticate(self, request):
token =request.GET.get("token")
print(token)
ret = models.Token.objects.filter(token=token).first()
if ret:
# 如果登陆成功了 那就直接下一步
return None
else:
raise exceptions.APIException("没有登陆")
11、检验
# 最后在postman这个工具中,用get查询, 如果携带了token就能查出详细的信息,如果没有就返回先登陆
http://127.0.0.1:8000/bookDetail/2?token=66c4bc0a-2f2a-40a3-81f7-5dcb075e7e3f
12、全局使用auth
# settings.py文件中定义, 所有的组件都可以放在这里
REST_FRAMEWORK = {
"DEFAULT_AUTHENTICATION_CLASSES": [
'app01.myauth.AuthUser', # 全局使用认证
]
}
13、局部使用
类中直接使用
authentication_classes = [AuthUser, ]
14、局部禁用
类中直接使用
authentication_classes = []
15、BaseAuthentication
继承基础组件, 也可以不继承
from rest_framework.authentication import BaseAuthentication
# 这个基础组件其实啥也没写, 关键在于就是继承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