前戏
大家都知道http协议是无状态的,每次发送请求他们怎么知道我们是不是登录过呢?我们可以在用户登录之后给用户一个“暗号”,下次请求的时候带着这个“暗号”来。我们拿自己存的和携带过来的进行对比,如果一样,就可以认为是登录过的。
认证
先来创建一张用户表
class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) token = models.UUIDField(null=True, blank=True) # 随机字符串
在进行数据库的迁移,在数据库里添加几条数据。
接下来就可以写我们的认证了,新建个py文件,写入如下内容,假设前端妹子给我们传来的token是在url里
from .models import User from rest_framework.exceptions import AuthenticationFailed from rest_framework.authentication import BaseAuthentication class MyAuth(BaseAuthentication): def authenticate(self, request): # 必须是这个函数名 # 拿到前端传来的token,判断token是否存在 token = request.query_params.get('token', '') if not token: raise AuthenticationFailed("缺少token") user_obj = User.objects.filter(token=token).first() if not user_obj: raise AuthenticationFailed("token不合法") return (user_obj, token)
token在请求头里
写个视图测试
class TestView(APIView): # 添加认证 authentication_classes = [MyAuth,] # 必须为可迭代对象 def get(self, request): return Response('认证')
这样只是个一个方法添加了认证,也可以添加全局的认证,在settings.py文件里
REST_FRAMEWORK = { # 默认使用的版本控制类 'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning', # 允许的版本 'ALLOWED_VERSIONS': ['v1', 'v2'], # 版本使用的参数名称 'VERSION_PARAM': 'version', # 默认使用的版本 'DEFAULT_VERSION': 'v1', # 配置全局认证 'DEFAULT_AUTHENTICATION_CLASSES': ["BRQP.utils.MyAuth", ] }
全局认证后在不需要认证的类中添加 authentication_classes = []
权限
我们都看过app上的电影,vip可以看一些视频,不是vip就看不了。因为vip的权限比非vip的权限大。那程序中的权限是什么样的呢?假设我们有一个系统,里面有添加学员,查看学员的功能。有些用户两个功能都有,而有些用户只有添加学员的功能。这里就要用到权限控制了。
在DRF的源码里,权限是在认证之后的。我们在执行权限的时候,认证已经执行结束了。
我们的权限类一定要有个has_permission方法,否则会抛出异常。
我们来写一个权限的demo。在上面的model类里给表在加一个type类,表示我们的权限。
from django.db import models class User(models.Model): name = models.CharField(max_length=32) pwd = models.CharField(max_length=32) token = models.UUIDField(null=True, blank=True) # 随机字符串 type = models.IntegerField(choices=((1, '普通用户'), (2, 'vip用户')), default=1) # 权限字段
在设置一个路由
from django.conf.urls import url ,include from .views import LoginView, TestView, TestPermission urlpatterns = [ url(r'^login/', LoginView.as_view()), url(r'^test/', TestView.as_view()), url(r'^permission/', TestPermission.as_view()), # 权限路由 ]
然后我们去写我们的权限类,新建一个permission.py文件
class MyPermission(object): message = '权限不足' # 提示信息 def has_permission(self, request, view): # 必须这个名 # 权限逻辑,认证已经执行完了 user_obj = request.user # 因为认证已经执行完了,所以有request.user print(user_obj) if user_obj.type == 1: # 返回的是个布尔值 return False else: return True
在去写我们的测试视图
class TestPermission(APIView): authentication_classes = [MyAuth, ] # 认证 permission_classes = [MyPermission, ] # 权限 def get(self, request): return Response("恭喜你,你有访问权限")
当有权限时(type=2)
无权限时(type=1)
DRF也给我们提供了一些权限类,都在permission类里
from rest_framework import permissions