1, 先写一个APP, 名字叫auth_test
1.1 urls.py文件内容如下:
path('dog/', views.DogView.as_view())
1.2 views.py 文件内容如下
from django.views import View
from rest_framework.views import APIView
class DogView(APIView):
'''
根据APIView源码,可以看到他是继承自django的View,这个APIView类里面的dispatch()函数,已经是被restframework 改装过的了,里面的功能增加
了很多,传递过来的request参数也被加工过
'''
def get(self,request, *args, **kwargs):
ret = {
'code': 1000,
'msg': 'xxx'
}
return HttpResponse(json.dumps(ret), status=201)
def post(self, request, *args, **kwargs):
return HttpResponse("创建dog")
def put(self, request, *args, **kwargs):
return HttpResponse('更新dog')
def delete(self, request, *args, **kwargs):
return HttpResponse('删除dog')
查看APIView中的dispatch()函数代码,看到如下:
所以经过restframework的APIView之后,request,变化了,增加了一些验证类,解析器,限流措施的类,这些类可以配置使用,也可以不设置,不设置就没有用。
在这里点击看Request()的类型:如下图所示:
把上面图里面的request, parsers, authen…, nego…, parser_c… 当做参数传递给下面图里面的Request()类,在这个类里面初始化之后,在返回给上面图片里面的initialize_request()
同时可以看到Request类里面的参数和函数结构如下所示:
我们就可以从总看到有user, data, auth, content_type等等
在这里单独拿authenticators=self.get_authenticators()来找到对应的函数.
可以看到在这里下面图片:所以经过加工过后的request里面有关于授权的类的实例, 并且不只一个,有好多个,他们组成一个列表. 其实就是一个列表,只不过这个列表中的每一项都是类的实例而已.不要想复杂了.
经过上面的图片可以看到列表生成式里面的 self.authentication_classes 这个东西,再点击之后,跳转到APIView的开头就是如下: 说明这里其实是读取的是restframework 配置文件里面的类实例。
综上一个流程就可以看到,使用restframework 的apiview之后,request经过封装加工之后,集成了一些其他的功能,这些功能以类的形式存在,可以设置在配置文件setttings.py中(因为最后面找到尽头就是配置文件里面),也可以设置在我们手写的views.py中,或者引入到views.py中去,因为一旦我们自己写相关的类,并且把他实例化之后,程序就会在我们手写的views.py这个层级内找相关的类实例。为啥这样,其实是因为类继承的关系,如果我们自己写了,就不会去父类中找了,如果我们没有写,因为APIView是类的缘故,所以会向上找。
所以对于一些权限,认证,限流,之类的我们可以利用restframwork的这些机制,直接在类中实现,然后引入views.py 中,或者直接在views.py中写。就可以实现这些功能。就不用用django的那个中间件实现了。
在看下图:
看上图,点击self.perform_authentication(request), 转到下面的图片上面的函数里面:
看上面图片:我们到Request()对象中找user 属性,如下图:
看上图: 发现authenticate()函数并没有写任何逻辑代码,所以如果我们自定义 验证类的话,就必须重写这个方法。实现自己的登录验证逻辑。
3.写一个views.py
下面的class MyAuthentication()就是我们一般实现restframework 认证的基本操作,就是写一个类,重写两个方法,写上认证的逻辑,然后在views中引用就可以,如果多个就用列表的形式阔进来,则这个views.py 就会一个一个的验证列表中的验证类。
所以如果有多个验证规则,就可以拆分成多个类,然后在views中用列表括起来就可以了。
from django.shortcuts import render
from django.http import HttpResponse
import json
from rest_framework.authentication import BasicAuthentication
from rest_framework import exceptions
###########restframework 授权部分##################
from django.views import View
from rest_framework.views import APIView
#这里我们自己尝试写一个验证类, 重写authenticate()方法,实现自己的认证逻辑
#浏览器url --> http://127.0.0.1/dog/?token=123 这个123是随机的,这个url就可以成功返回get()函数里面的代码。
class MyAuthentication(object):
def authenticate(self, request): #重写authenticate()方法,实现自己的认证逻辑
token = request._request.GET.get('token') # 这里第一个request是封装集成之后的request,第二个_request是原生的request. 这里参考Request()类。
#这里举例子,假设用户请求的时候,验证带没带token,如果带了就返回元祖,这个返回元祖是验证类要求的,(user, token)
#可以拿到用户登录的用户名和密码,然后去数据库校验,这里没有做这个
if not token:
raise exceptions.AuthenticationFailed('用户认证失败') #假设没有token,返回用户认证失败。
return ('lxbai', None) #这个是验证成功了之后,返回的用户名和token的元祖,我们就可以在view中打印出来看一是不是
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
class DogView(APIView):
'''
根据APIView源码,可以看到他是继承自django的View,这个APIView类里面的dispatch()函数,已经是被restframework 改装过的了,里面的功能增加
了很多,传递过来的request参数也被加工过
'''
authentication_classes = [MyAuthentication,]
print(request.user) #打印我们调用验证器之后返回的元祖里面的内容,是上面的那个 lixbai
def get(self,request, *args, **kwargs):
ret = {
'code': 1000,
'msg': 'xxx'
}
return HttpResponse(json.dumps(ret), status=201)
def post(self, request, *args, **kwargs):
return HttpResponse("创建dog")
def put(self, request, *args, **kwargs):
return HttpResponse('更新dog')
def delete(self, request, *args, **kwargs):
return HttpResponse('删除dog')