REST_FRAMEWORK = { ‘DEFAULT_VERSION‘: ‘v1‘, # 默认版本 ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], # 允许的版本 ‘VERSION_PARAM‘: ‘version‘ # URL中获取值的key }
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view(), name=‘test‘), ]
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import AcceptHeaderVersioning class TestView(APIView): versioning_class = AcceptHeaderVersioning def get(self, request, *args, **kwargs): # 获取版本 HTTP_ACCEPT头 print(request.version) # 获取版本管理的类 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse(‘test‘, request=request) print(reverse_url) return Response(‘GET请求,响应内容‘) def post(self, request, *args, **kwargs): return Response(‘POST请求,响应内容‘) def put(self, request, *args, **kwargs): return Response(‘PUT请求,响应内容‘)
d. 基于主机名方法
如:v1.example.com
ALLOWED_HOSTS = [‘*‘] REST_FRAMEWORK = { ‘DEFAULT_VERSION‘: ‘v1‘, # 默认版本 ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], # 允许的版本 ‘VERSION_PARAM‘: ‘version‘ # URL中获取值的key }
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view(), name=‘test‘), ]
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import HostNameVersioning class TestView(APIView): versioning_class = HostNameVersioning def get(self, request, *args, **kwargs): # 获取版本 print(request.version) # 获取版本管理的类 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse(‘test‘, request=request) print(reverse_url) return Response(‘GET请求,响应内容‘) def post(self, request, *args, **kwargs): return Response(‘POST请求,响应内容‘) def put(self, request, *args, **kwargs): return Response(‘PUT请求,响应内容‘)
e. 基于django路由系统的namespace
如:example.com/v1/users/
REST_FRAMEWORK = { ‘DEFAULT_VERSION‘: ‘v1‘, # 默认版本 ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], # 允许的版本 ‘VERSION_PARAM‘: ‘version‘ # URL中获取值的key }
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^v1/‘, ([ url(r‘test/‘, TestView.as_view(), name=‘test‘), ], None, ‘v1‘)), url(r‘^v2/‘, ([ url(r‘test/‘, TestView.as_view(), name=‘test‘), ], None, ‘v2‘)), ]
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.versioning import NamespaceVersioning class TestView(APIView): versioning_class = NamespaceVersioning def get(self, request, *args, **kwargs): # 获取版本 print(request.version) # 获取版本管理的类 print(request.versioning_scheme) # 反向生成URL reverse_url = request.versioning_scheme.reverse(‘test‘, request=request) print(reverse_url) return Response(‘GET请求,响应内容‘) def post(self, request, *args, **kwargs): return Response(‘POST请求,响应内容‘) def put(self, request, *args, **kwargs): return Response(‘PUT请求,响应内容‘)
f. 全局使用
REST_FRAMEWORK = { ‘DEFAULT_VERSIONING_CLASS‘:"rest_framework.versioning.URLPathVersioning", ‘DEFAULT_VERSION‘: ‘v1‘, ‘ALLOWED_VERSIONS‘: [‘v1‘, ‘v2‘], ‘VERSION_PARAM‘: ‘version‘ }
DRF的认证
上面讲版本的时候我们知道~在dispatch方法里~执行了initial方法~~那里初始化了我们的版本~~
如果我们细心我们能看到~版本的下面其实就是我们的认证,权限,频率组件了~~
我们先看看我们的认证组件~~
我们进去我们的认证看下~~
我们这个权限组件返回的是request.user,那我们这里的request是新的还是旧的呢~~
我们的initial是在我们request重新赋值之后的~所以这里的request是新的~也就是Request类实例对象~~
那这个user一定是一个静态方法~我们进去看看~~
我没在这里反复的截图跳转页面~~大家可以尝试着自己去找~~要耐心~~细心~~
我们通过上面基本可以知道我们的认证类一定要实现的方法~~以及返回值类型~~以及配置的参数authentication_classes~
认证的详细用法
a. 用户url传入的token认证
from django.conf.urls import url, include from web.viewsimport TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view()), ]
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptions token_list = [ ‘sfsfss123kuf3j123‘, ‘asijnfowerkkf9812‘, ] class TestAuthentication(BaseAuthentication): def authenticate(self, request): """ 用户认证,如果验证成功后返回元组: (用户,用户Token) :param request: :return: None,表示跳过该验证; 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置 self._authenticator = None if api_settings.UNAUTHENTICATED_USER: self.user = api_settings.UNAUTHENTICATED_USER() else: self.user = None if api_settings.UNAUTHENTICATED_TOKEN: self.auth = api_settings.UNAUTHENTICATED_TOKEN() else: self.auth = None (user,token)表示验证通过并设置用户名和Token; AuthenticationFailed异常 """ val = request.query_params.get(‘token‘) if val not in token_list: raise exceptions.AuthenticationFailed("用户认证失败") return (‘登录用户‘, ‘用户token‘) 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. """ # 验证失败时,返回的响应头WWW-Authenticate对应的值 pass class TestView(APIView): authentication_classes = [TestAuthentication, ] permission_classes = [] def get(self, request, *args, **kwargs): print(request.user) print(request.auth) return Response(‘GET请求,响应内容‘) def post(self, request, *args, **kwargs): return Response(‘POST请求,响应内容‘) def put(self, request, *args, **kwargs): return Response(‘PUT请求,响应内容‘)
b. 请求头认证
from django.conf.urls import url, include from web.viewsimport TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view()), ]
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptions token_list = [ ‘sfsfss123kuf3j123‘, ‘asijnfowerkkf9812‘, ] class TestAuthentication(BaseAuthentication): def authenticate(self, request): """ 用户认证,如果验证成功后返回元组: (用户,用户Token) :param request: :return: None,表示跳过该验证; 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置 self._authenticator = None if api_settings.UNAUTHENTICATED_USER: self.user = api_settings.UNAUTHENTICATED_USER() else: self.user = None if api_settings.UNAUTHENTICATED_TOKEN: self.auth = api_settings.UNAUTHENTICATED_TOKEN() else: self.auth = None (user,token)表示验证通过并设置用户名和Token; AuthenticationFailed异常 """ import base64 auth = request.META.get(‘HTTP_AUTHORIZATION‘, b‘‘) if auth: auth = auth.encode(‘utf-8‘) auth = auth.split() if not auth or auth[0].lower() != b‘basic‘: raise exceptions.AuthenticationFailed(‘验证失败‘) if len(auth) != 2: raise exceptions.AuthenticationFailed(‘验证失败‘) username, part, password = base64.b64decode(auth[1]).decode(‘utf-8‘).partition(‘:‘) if username == ‘alex‘ and password == ‘123‘: return (‘登录用户‘, ‘用户token‘) else: raise exceptions.AuthenticationFailed(‘用户名或密码错误‘) 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. """ return ‘Basic realm=api‘ class TestView(APIView): authentication_classes = [TestAuthentication, ] permission_classes = [] def get(self, request, *args, **kwargs): print(request.user) print(request.auth) return Response(‘GET请求,响应内容‘) def post(self, request, *args, **kwargs): return Response(‘POST请求,响应内容‘) def put(self, request, *args, **kwargs): return Response(‘PUT请求,响应内容‘)
c. 多个认证规则
from django.conf.urls import url, include from web.views.s2_auth import TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view()), ]
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptions token_list = [ ‘sfsfss123kuf3j123‘, ‘asijnfowerkkf9812‘, ] class Test1Authentication(BaseAuthentication): def authenticate(self, request): """ 用户认证,如果验证成功后返回元组: (用户,用户Token) :param request: :return: None,表示跳过该验证; 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置 self._authenticator = None if api_settings.UNAUTHENTICATED_USER: self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户 else: self.user = None if api_settings.UNAUTHENTICATED_TOKEN: self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None else: self.auth = None (user,token)表示验证通过并设置用户名和Token; AuthenticationFailed异常 """ import base64 auth = request.META.get(‘HTTP_AUTHORIZATION‘, b‘‘) if auth: auth = auth.encode(‘utf-8‘) else: return None print(auth,‘xxxx‘) auth = auth.split() if not auth or auth[0].lower() != b‘basic‘: raise exceptions.AuthenticationFailed(‘验证失败‘) if len(auth) != 2: raise exceptions.AuthenticationFailed(‘验证失败‘) username, part, password = base64.b64decode(auth[1]).decode(‘utf-8‘).partition(‘:‘) if username == ‘alex‘ and password == ‘123‘: return (‘登录用户‘, ‘用户token‘) else: raise exceptions.AuthenticationFailed(‘用户名或密码错误‘) 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. """ # return ‘Basic realm=api‘ pass class Test2Authentication(BaseAuthentication): def authenticate(self, request): """ 用户认证,如果验证成功后返回元组: (用户,用户Token) :param request: :return: None,表示跳过该验证; 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置 self._authenticator = None if api_settings.UNAUTHENTICATED_USER: self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户 else: self.user = None if api_settings.UNAUTHENTICATED_TOKEN: self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None else: self.auth = None (user,token)表示验证通过并设置用户名和Token; AuthenticationFailed异常 """ val = request.query_params.get(‘token‘) if val not in token_list: raise exceptions.AuthenticationFailed("用户认证失败") return (‘登录用户‘, ‘用户token‘) 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 TestView(APIView): authentication_classes = [Test1Authentication, Test2Authentication] permission_classes = [] def get(self, request, *args, **kwargs): print(request.user) print(request.auth) return Response(‘GET请求,响应内容‘) def post(self, request, *args, **kwargs): return Response(‘POST请求,响应内容‘) def put(self, request, *args, **kwargs): return Response(‘PUT请求,响应内容‘) views.py#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptions token_list = [ ‘sfsfss123kuf3j123‘, ‘asijnfowerkkf9812‘, ] class Test1Authentication(BaseAuthentication): def authenticate(self, request): """ 用户认证,如果验证成功后返回元组: (用户,用户Token) :param request: :return: None,表示跳过该验证; 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置 self._authenticator = None if api_settings.UNAUTHENTICATED_USER: self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户 else: self.user = None if api_settings.UNAUTHENTICATED_TOKEN: self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None else: self.auth = None (user,token)表示验证通过并设置用户名和Token; AuthenticationFailed异常 """ import base64 auth = request.META.get(‘HTTP_AUTHORIZATION‘, b‘‘) if auth: auth = auth.encode(‘utf-8‘) else: return None print(auth,‘xxxx‘) auth = auth.split() if not auth or auth[0].lower() != b‘basic‘: raise exceptions.AuthenticationFailed(‘验证失败‘) if len(auth) != 2: raise exceptions.AuthenticationFailed(‘验证失败‘) username, part, password = base64.b64decode(auth[1]).decode(‘utf-8‘).partition(‘:‘) if username == ‘alex‘ and password == ‘123‘: return (‘登录用户‘, ‘用户token‘) else: raise exceptions.AuthenticationFailed(‘用户名或密码错误‘) 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. """ # return ‘Basic realm=api‘ pass class Test2Authentication(BaseAuthentication): def authenticate(self, request): """ 用户认证,如果验证成功后返回元组: (用户,用户Token) :param request: :return: None,表示跳过该验证; 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置 self._authenticator = None if api_settings.UNAUTHENTICATED_USER: self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户 else: self.user = None if api_settings.UNAUTHENTICATED_TOKEN: self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None else: self.auth = None (user,token)表示验证通过并设置用户名和Token; AuthenticationFailed异常 """ val = request.query_params.get(‘token‘) if val not in token_list: raise exceptions.AuthenticationFailed("用户认证失败") return (‘登录用户‘, ‘用户token‘) 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 TestView(APIView): authentication_classes = [Test1Authentication, Test2Authentication] permission_classes = [] def get(self, request, *args, **kwargs): print(request.user) print(request.auth) return Response(‘GET请求,响应内容‘) def post(self, request, *args, **kwargs): return Response(‘POST请求,响应内容‘) def put(self, request, *args, **kwargs): return Response(‘PUT请求,响应内容‘)
d. 认证和权限
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view()), ]
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.permissions import BasePermission from rest_framework.request import Request from rest_framework import exceptions token_list = [ ‘sfsfss123kuf3j123‘, ‘asijnfowerkkf9812‘, ] class TestAuthentication(BaseAuthentication): def authenticate(self, request): """ 用户认证,如果验证成功后返回元组: (用户,用户Token) :param request: :return: None,表示跳过该验证; 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置 self._authenticator = None if api_settings.UNAUTHENTICATED_USER: self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户 else: self.user = None if api_settings.UNAUTHENTICATED_TOKEN: self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None else: self.auth = None (user,token)表示验证通过并设置用户名和Token; AuthenticationFailed异常 """ val = request.query_params.get(‘token‘) if val not in token_list: raise exceptions.AuthenticationFailed("用户认证失败") return (‘登录用户‘, ‘用户token‘) 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 TestPermission(BasePermission): message = "权限验证失败" def has_permission(self, request, view): """ 判断是否有权限访问当前请求 Return `True` if permission is granted, `False` otherwise. :param request: :param view: :return: True有权限;False无权限 """ if request.user == "管理员": return True # GenericAPIView中get_object时调用 def has_object_permission(self, request, view, obj): """ 视图继承GenericAPIView,并在其中使用get_object时获取对象时,触发单独对象权限验证 Return `True` if permission is granted, `False` otherwise. :param request: :param view: :param obj: :return: True有权限;False无权限 """ if request.user == "管理员": return True class TestView(APIView): # 认证的动作是由request.user触发 authentication_classes = [TestAuthentication, ] # 权限 # 循环执行所有的权限 permission_classes = [TestPermission, ] def get(self, request, *args, **kwargs): # self.dispatch print(request.user) print(request.auth) return Response(‘GET请求,响应内容‘) def post(self, request, *args, **kwargs): return Response(‘POST请求,响应内容‘) def put(self, request, *args, **kwargs): return Response(‘PUT请求,响应内容‘)
e. 全局使用
REST_FRAMEWORK = { ‘UNAUTHENTICATED_USER‘: None, ‘UNAUTHENTICATED_TOKEN‘: None, "DEFAULT_AUTHENTICATION_CLASSES": [ "web.utils.TestAuthentication", ], "DEFAULT_PERMISSION_CLASSES": [ "web.utils.TestPermission", ], }
from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r‘^test/‘, TestView.as_view()), ]
#!/usr/bin/env python # -*- coding:utf-8 -*- from rest_framework.views import APIView from rest_framework.response import Response class TestView(APIView): def get(self, request, *args, **kwargs): # self.dispatch print(request.user) print(request.auth) return Response(‘GET请求,响应内容‘) def post(self, request, *args, **kwargs): return Response(‘POST请求,响应内容‘) def put(self, request, *args, **kwargs): return Response(‘PUT请求,响应内容‘)