django rest framework框架
这是我参与8月更文挑战的第23天,活动详情查看:8月更文挑战
感激相遇 你好 我是y大壮
作者:y大壮
链接:juejin.cn/user/756923… 来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
🌊🌈关于前言:
文章部分内容及图片出自网络,如有问题请与我本人联系
🌊🌈关于内容:
作者:y大壮
链接:juejin.cn/post/699902…
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
-
pip install djangorestframework
-
在settings中配置
INSTALLED_APPS = [ 'rest_framework', # DRF ]
1、认证
认证组件一般用在用户的登录注册上,用于判断当前的用户是否合法,并跳转到登陆成功或失败页面。
有些API需要用户登录成功之后,才能访问;有些无需登录就能访问。
解决方式:
把token值存放起来
1.1 自定义认证方式(基本使用):
APIView为我们提供了很多的方法, 当用户登录或者注册的时候,我们会给用户token。所以我们在进行认证的时候,只用去检测token在不在就可以了
!! 我们是继承了认证的方法,所有authenticate_header一定要加上
from django.views import View
from rest_framework.views import APIView
from rest_framework.authentication import BasicAuthentication
from rest_framework import exceptions
from rest_framework.request import Request
class MyAuthentication(object):
def authenticate(self,request):
token = request._request.GET.get('token') # 获取token值
# 获取用户名和密码,去数据校验
if not token:
raise exceptions.AuthenticationFailed('用户认证失败')
return ("alex",None) # 有token值的时候干嘛干嘛
def authenticate_header(self,val):
pass
class DogView(APIView):
authentication_classes = [MyAuthentication,]
def get(self,request,*args,**kwargs):
print(request)
print(request.user)
ret = { # 设置响应消息
'code':1000,
'msg':'xxx'
}
return HttpResponse(json.dumps(ret),status=201)
def post(self,request,*args,**kwargs):
return HttpResponse('创建')
def put(self,request,*args,**kwargs):
return HttpResponse('更新')
def delete(self,request,*args,**kwargs):
return HttpResponse('删除')
1.2 认证流程原理:
dispatch开始
# 1.APIView下的dispatch
def dispatch(self, request, *args, **kwargs):
self.args = args
self.kwargs = kwargs
# 获取的参数
# 把获取的参数,经过initialize_request构建成新的request
request = self.initialize_request(request, *args, **kwargs)
# 获取原生request,request._request
# 获取认证类的对象,request.authenticators
self.request = request
self.headers = self.default_response_headers # deprecate?
# 2.initial(self, request, *args, **kwargs):
# 3.perform_authentication(self, request)
# 4.原生的request
@property
def user(self):
"""
Returns the user associated with the current request, as authenticated
by the authentication classes provided to the request.
"""
if not hasattr(self, '_user'):
with wrap_attributeerrors():
# 获取认证对象,进行一步的认证
self._authenticate() # 进入认证
return self._user
# 5.self._authenticate()、进入def _not_authenticated(self):方法,为None,或者有值
def _authenticate(self):
"""
Attempt to authenticate the request using each authentication instance
in turn.
"""
# [BasicAuthentication对象,]
for authenticator in self.authenticators: # 遍历认证对象,执行认证方法
try:
# 执行认证类的authenticate方法
# 1. 如果authenticate方法抛出异常,self_not_authenticate()执行
# 2. 有返回值必须是元组:(request.user,request.auth)
# 3. 返回None的话,下个认证来进行处理
user_auth_tuple = authenticator.authenticate(self) # 执行这个对象的认证方法(认证是否以及登录),如果没有就报错
except exceptions.APIException:
self._not_authenticated() # 没有进入_not_authenticated,返回对应的错误消息
raise
if user_auth_tuple is not None: # 给响应的参数赋值
self._authenticator = authenticator
self.user, self.auth = user_auth_tuple
return
self._not_authenticated()
2、自定义认证类示例
class Authtication(object):
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('用户未认证')
return (token_obj.user, token_obj) # 在rest fromwork内部会将这二个字段赋值给request,以供后续的使用(对应request.user,request.auth)
def authenticate_header(self, request):
pass
class OrderView(APIView):
authentication_classes = [Authtication, ] # 方式二:
def get(self, request, *args, **kwargs):
# 方式一:
# token = request._request.GET.get('token')
# if not token:
# raise exceptions.AuthenticationFailed('用户未认证')
ret = {'code': 1000, 'message': 'ok!', 'data': None}
try:
ret['data'] = ORDER_DICT
except Exception as e:
ret['code'] = 1001
ret['message'] = '找不到服务器'
return JsonResponse(ret)
3、自定义全局认证&局部认证
全局认证
-
把自定义的认证类封装到文件夹中
# app02.utils.auth.py from rest_framework import exceptions from .. import models class Authtication(object): 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('用户未认证') return (token_obj.user, token_obj) # 在rest fromwork内部会将这二个字段赋值给request,以供后续的使用(对应request.user,request.auth) def authenticate_header(self, request): pass class FirstAuthtication(object): def authenticate(self, request): pass # pass返回的是None (搞成匿名用户的示例) def authenticate_header(self, request): pass -
在settings中配置
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ['app02.utils.auth.FirstAuthtication', 'app02.utils.auth.Authtication'] } -
使用
# 因为这样定义是全局的,所以所有的视图都可以使用。 # 我们可以设置authentication_classes=[] 这样就可以不用使用全局的认证 class AuthLoginView(APIView): """用户登录""" authentication_classes = []
局部认证
# 自定义好后直接使用就可以authentication_classes = [Authtication, ]
class Authtication(object):
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('用户未认证')
return (token_obj.user, token_obj) # 在rest fromwork内部会将这二个字段赋值给request,以供后续的使用(对应request.user,request.auth)
def authenticate_header(self, request):
pass
class OrderView(APIView):
authentication_classes = [Authtication, ] # 方式二:
def get(self, request, *args, **kwargs):
# 方式一:
# token = request._request.GET.get('token')
# if not token:
# raise exceptions.AuthenticationFailed('用户未认证')
ret = {'code': 1000, 'message': 'ok!', 'data': None}
try:
ret['data'] = ORDER_DICT
except Exception as e:
ret['code'] = 1001
ret['message'] = '找不到服务器'
return JsonResponse(ret)
4、匿名用户
-
settings.py
匿名用户就是设置request.user和request.auth为None没有信息
REST_FRAMEWORK = { # 'DEFAULT_AUTHENTICATION_CLASSES': ['app02.utils.auth.FirstAuthtication', 'app02.utils.auth.Authtication'], 'DEFAULT_AUTHENTICATION_CLASSES': ['app02.utils.auth.FirstAuthtication'], # 匿名用户(因为我们在封装的时候什么都没有写,让它返回None) # 'UNAUTHENTICATED_USER': lambda: '匿名用户', 'UNAUTHENTICATED_USER': None, 'UNAUTHENTICATED_TOKEN': None, } -
app02.utils.auth.py
class FirstAuthtication(object): def authenticate(self, request): print('匿名用户') pass # pass返回的是None (搞成匿名用户的示例) def authenticate_header(self, request): pass
5、认证Authentication(resf自带认证)
-
在settings.py配置
REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework.authentication.SessionAuthentication', # session认证 'rest_framework.authentication.BasicAuthentication', # 基本认证 ) } -
每个视图通过authentication_classess来添加认证
from rest_framework.authentication import SessionAuthentication, BasicAuthentication from rest_framework.views import APIView class ExampleView(APIView): authentication_classes = (SessionAuthentication, BasicAuthentication) -
认证失败会有两种可能的返回值
-
401 Unauthorized 未认证
-
403 Permission Denied 权限被禁止