REST_FRAMEWORK重要组件--->authentication
1.认证(authenticate)
(1).对于某些API来说是需要做完访问认证才能查看网页内容的,比如说get请求带token认证字段。
(2).对于认证的流程来说,无论是认证、权限、节流、版本、
解析器还是其他的组件,入口都是self.dispatch()
(3).认证的流程为 请求进来->self.dispatch()>request=self.initialize_request(request,*args,kwargs)
->return Request() 返回一个Request对象,里面包括一个原生的request和self.get_Authenticators()方法get_Authenticators()方法是将一个authentication_Classes列表里面的对象进行实例化。首先找继承BaseAuthentication的视图函数是否有authenticate/authenticate_header这两个函数,如果没有,找父类的。其中authenticate回去挨个遍历authentication_classes列表中的认证,如果认证成功了,才会去执行dispatch中剩下来的getattr()去进行反射,去执行对相应method的操作,认证可以是单个,也可是多个,也可以为空。
(4).认证操作继承BaseAuthentication里面有authenticate和authenticate_header 两个函数必须要重写。其中authenticate(self,request)函数里面,获取url参数可以为request._request.Get.get(‘token’),authenticate_header(self,request)函数里面,可以省略,直接pass过。
(5).部分认证和全局认证:所谓的部分认证就是在app下面写了一个自定义的authentication类,比如名字叫MyAuthentication(BaseAuthentication)类
class MyAuthentication(BaseAuthentication):
def authenticate(self, request):
token=request._request.GET.get('token')
token_obj=models.Usertoken.objects.filter(token=token).first()
print(token_obj)
if not token_obj:
raise exceptions.AuthenticationFailed("用户登录失败")
return (token_obj.user,token_obj) #这一步是关键,如果没有返回这两个参数,默认是匿名用户登录的
#这对于权限来说是致命的,因为认证返回None,则权限不能利用request.user.login_type字段
#user是UserInfo表和UserToken表的一对一字段。权限验证就会报错报错:
#'AnonymousUser' object has no attribute 'login_type'
def authenticate_header(self, request):
pass
from rest_framework.views import APIView
# Create your views here.
from django.http import JsonResponse
from test3 import models
def md5(user):
import hashlib
import time
ctime=str(time.time())
m=hashlib.md5(bytes(user,encoding='utf-8'))
m.update(bytes(ctime,encoding='utf-8'))
return m.hexdigest()
class Authview(APIView):
authentication_classes = [MyAuthentication,]
def post(self,request,*args,**kwargs):
#self.dispatch()
ret={
'code':1000,
'msg':None,
}
try:
user = request._request.POST.get('username')
pwd = request._request.POST.get('password')
obj=models.Userinfo.objects.filter(username=user,password=pwd).first()
if not obj:
ret['code']=1001
ret['msg']="您输入的账户或密码错误"
token =md5(user)
#update_or_create传参时候的user是Usertoken里面的一对一字段
models.Usertoken.objects.update_or_create(user=obj,defaults={'token':token})
ret['token']=token
except Exception as e:
print(e)
return JsonResponse(ret)
AuthView这个类就是一个部分认证的类,在每个类去调用这个MyAuthentication的时候都要写上这么一句authentication_classes=[MyAuthentication,] 。
何谓全局认证?就是在app下专门写一个authentication类,在settings中设置一个REST_FRAMEWORK{}的字典变量。里面的认证可以是一个,也可以是多个。
"DEFAULT_AUTHENTICATION_CLASSES":['test3.utils.auth.Authenticationfirst',],
做完全局变量最重要的一点是按照不同的认证在视图类下重写authentication_classes列表,比如全局变量中有两个认证token类,那就意味着继承每个视图类都需要进行一个token的认证。如果想让某个类免除认证就需要在免除认证的视图下写上authentication_classes = [,]。
解析上面的例子:上面的例子其实就是做了一个用户利用token认证和username、password登陆的用户登录。虽然token、username、password三者是同时传给后台,但是却是先做的认证,认证通过了,再去检验username、password字段的值是否正确。利用MD5配合time.time()随机生成一个token字符串,再利用ORM的update_or_create(不存在即创建,存在则更新)进行存储。
`