权限
认证,根据用户携带的 token/其他 获取当前用户信息。
权限,读取认证中获取的用户信息,判断当前用户是否有权限访问,例如:普通用户、管理员、超级用户,不同用户具有不同的权限。
class UserInfo(models.Model):
role_choices = ((1, "普通用户"), (2, "管理员"), (3, "超级管理员"),)
role = models.IntegerField(verbose_name="角色", choices=role_choices, default=1)
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=64)
token = models.CharField(verbose_name="TOKEN", max_length=64, null=True, blank=True)
import uuid
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from rest_framework.exceptions import AuthenticationFailed
from app01 import models
class AuthView(APIView):
""" 用户登录认证 """
authentication_classes = []
permission_classes = []
def post(self, request, *args, **kwargs):
print(request.data) # {"username": "wupeiqi", "password": "123"}
username = request.data.get('username')
password = request.data.get('password')
user_object = models.UserInfo.objects.filter(username=username, password=password).first()
if not user_object:
return Response({"code": 1000, "data": "用户名或密码错误"})
token = str(uuid.uuid4())
user_object.token = token
user_object.save()
return Response({"code": 0, "data": {"token": token, "name": username}})
class TokenAuthentication(BaseAuthentication):
def authenticate(self, request):
token = request.query_params.get("token")
if not token:
raise AuthenticationFailed({"code": 1002, "data": "认证失败"})
user_object = models.UserInfo.objects.filter(token=token).first()
if not user_object:
raise AuthenticationFailed({"code": 1002, "data": "认证失败"})
return user_object, token
def authenticate_header(self, request):
return 'Bearer realm="API"'
class PermissionA(BasePermission):
message = {"code": 1003, 'data': "无权访问"}
def has_permission(self, request, view):
if request.user.role == 2:
return True
return False
# 暂时先这么写
def has_object_permission(self, request, view, obj):
return True
class OrderView(APIView):
authentication_classes = [TokenAuthentication, ]
permission_classes = [PermissionA,]
def get(self, request, *args, **kwargs):
print(request.user)
return Response({"code": 0, "data": {"user": None, 'list': [1, 2, 3]}})
class PayView(APIView):
authentication_classes = [TokenAuthentication, ]
permission_classes = [PermissionA, ]
def get(self, request, *args, **kwargs):
print(request.user)
return Response({"code": 0, "data": "数据..."})
关于多个权限类
当开发过程中需要用户同时具备多个权限(缺一不可)时,可以用多个权限类来实现。
权限组件内部处理机制:按照列表的顺序逐一执行 has_permission
方法,如果返回True,则继续执行后续的权限类;如果返回None或False,则抛出权限异常并停止后续权限类的执行。
# models.py
from django.db import models
class Role(models.Model):
""" 角色表 """
title = models.CharField(verbose_name="名称", max_length=32)
class UserInfo(models.Model):
""" 用户表 """
username = models.CharField(verbose_name="用户名", max_length=32)
password = models.CharField(verbose_name="密码", max_length=64)
token = models.CharField(verbose_name="TOKEN", max_length=64, null=True, blank=True)
roles = models.ManyToManyField(verbose_name="角色", to="Role")
# urls.py
from django.urls import path, re_path, include
from app01 import views
urlpatterns = [
path('api/auth/', views.AuthView.as_view()),
path('api/order/', views.OrderView.as_view()),
]
# views.py
import uuid
from rest_framework.views import APIView
from rest_framework.request import Request
from rest_framework.response import Response
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission
from rest_framework.exceptions import AuthenticationFailed
from app01 import models
class AuthView(APIView):
""" 用户登录认证 """
def post(self, request, *args, **kwargs):
print(request.data) # {"username": "wupeiqi", "password": "123"}
username = request.data.get('username')
password = request.data.get('password')
user_object = models.UserInfo.objects.filter(username=username, password=password).first()
if not user_object:
return Response({"code": 1000, "data": "用户名或密码错误"})
token = str(uuid.uuid4())
user_object.token = token
user_object.save()
return Response({"code": 0, "data": {"token": token, "name": username}})
class TokenAuthentication(BaseAuthentication):
def authenticate(self, request):
token = request.query_params.get("token")
if not token:
raise AuthenticationFailed({"code": 1002, "data": "认证失败"})
user_object = models.UserInfo.objects.filter(token=token).first()
if not user_object:
raise AuthenticationFailed({"code": 1002, "data": "认证失败"})
return user_object, token
def authenticate_header(self, request):
return 'Bearer realm="API"'
class PermissionA(BasePermission):
message = {"code": 1003, 'data': "无权访问"}
def has_permission(self, request, view):
exists = request.user.roles.filter(title="员工").exists()
if exists:
return True
return False
def has_object_permission(self, request, view, obj):
return True
class PermissionB(BasePermission):
message = {"code": 1003, 'data': "无权访问"}
def has_permission(self, request, view):
exists = request.user.roles.filter(title="主管").exists()
if exists:
return True
return False
def has_object_permission(self, request, view, obj):
return True
class OrderView(APIView):
authentication_classes = [TokenAuthentication, ]
permission_classes = [PermissionA, PermissionA]
def get(self, request, *args, **kwargs):
return Response({"code": 0, "data": {"user": None, 'list': [1, 2, 3]}})
class PayView(APIView):
authentication_classes = [TokenAuthentication, ]
permission_classes = [PermissionA, ]
def get(self, request, *args, **kwargs):
return Response({"code": 0, "data": "数据..."})
全局配置
REST_FRAMEWORK = {
"DEFAULT_PERMISSION_CLASSES":["xxxx.xxxx.xx.类名","xxxx.xxxx.xx.类名",]
}
底层源码实现
小结
- 权限
- 过程:执行所有的权限类的
has_permission
方法,只有所有都返回True时,才表示具有权限 - 结果:有权限则可以执行后续的视图,无权限则直接返回 自定义的错误信息
- 过程:执行所有的权限类的
若有错误与不足请指出,关注DPT一起进步吧!!!