Ⅰ 权限
【一】ACL(Access Control List,访问控制列表)
# ACL(Access Control List,访问控制列表)
将用户直接与与权限对接
permission表
id user_id 权限名
1 1 开直播
2 1 评论
【二】RBAC(Role-Based Access Control,基于角色的访问控制)
- 将用户与角色对接,然后角色与对象的权限对接
# 将用户与角色对接,然后角色与对象的权限对接
RBAC 是基于角色的访问控制(Role-Based Access Control )在 RBAC 中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便。
【三】ABAC(Attribute-Based Access Control,基于属性的访问控制)
# ABAC(Attribute-Based Access Control,基于属性的访问控制)
ABAC(Attribute-Based Access Control,基于属性的访问控制),又称为PBAC(Policy-Based Access Control,基于策略的访问控制),CBAC(Claims-Based Access Control,基于声明的访问控制)。
传统的ACL、RBAC的架构是{subject,action,object},而ABAC的架构是{subject,action,object,contextual}且为他们添加了parameter(参数)。
subject属性:比如用户的年龄、部门、角色、威望、积分等主题属性。
action属性:比如查看、读取、编辑、删除等行为属性。
object属性:比如银行账户、文章、评论等对象或资源属性。
contextual属性:比如时段、IP位置、天气等环境属性
【四】补充:auth的user表,密码加密-->同样的明文,加密后 密文不一样
# auth的user表,密码加密-->同样的明文,加密后 密文不一样
-pbkdf2_sha256:加密方式
-600000:过期时间
-uxJKoercOSxrWD1nwEitF8:盐
-7GKS8QnEMPkxbQYRrJRwQg1vtS+XrzER+j/JAkM+1/U= :密文pbkdf2_sha256$600000$uxJKoercOSxrWD1nwEitF8$7GKS8QnEMPkxbQYRrJRwQg1vtS+XrzER+j/JAkM+1/U=
auth的user表的对象有俩方法
# from django.contrib.auth.hashers import check_password 校验密码
user.check_password(明文密码)
# from django.contrib.auth.hashers import make_password 转化为密文
make_password(明文密码)-->User.object.create_user()
# 使用
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32) # 没有加密--明文
age = models.CharField(max_length=32)
@classmethod
def create_user(self, username, password):
password=make_password(password)
self.objects.create( password=密文密码)
User.create_user()
【五】 django 的 自带admin-->后台管理--6张表实现rbac权限控制
# django 的 自带admin--》后台管理--6张表实现rbac权限控制 具体点就是:rbac+acl
-admin+auth--->有rbac的权限
-分析:通过那些表实现rbac
-用户表;auth-user表:auth_user
用户和角色是多对多,有个中间表 auth_user_group
-角色(组):auth_group
角色和权限多对多:auth_group_permission
-权限:auth_permission
-django为了更细粒度的做权限划分,又多加了个
用户和权限多对多
auth_user_permission
【1】数据准备
- models.py
class Book(models.Model):
username = models.CharField(max_length=32)
- admin.py
# 这样在admin后台才能显示User表和Book表
from django.contrib import admin
# Register your models here.
from .models import User, Book
admin.site.register(User)
admin.site.register(Book)
- serialzier.py
from .models import Book
class BookSerialzier(serializers.ModelSerializer):
class Meta:
model=Book
fields='__all__'
- views.py
from .models import Book
from .serialzier import BookSerialzier
class BookView(APIView):
def get(self,request):
books=Book.objects.all().first()
# <class 'rest_framework.serializers.ListSerializer'>
# BookSerialzier
serialzier=BookSerialzier(instance=books,many=True)
print(type(serialzier))
return Response('ok')
- urls.py
from django.urls import path
from .views import BookView
urlpatterns = [
path('books/', BookView.as_view()),
]
- 前端展示
【2】修改app名字,表名字和表里的对象名字
(1)修改app名字
- apps.py
from django.apps import AppConfig
class Aoo01Config(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'aoo01'
verbose_name = '应用一'
(2)修改表名字
- models.py
class Book(models.Model):
username = models.CharField(max_length=32)
class Meta:
verbose_name='图书表'
verbose_name_plural='图书表'
(3)修改表里的对象名字
- models.py
class Book(models.Model):
username = models.CharField(max_length=32)
class Meta:
verbose_name='图书表'
verbose_name_plural='图书表'
def __str__(self):
return self.username
【3】添加不同权限分组
- 再添加一个UserInfo的用户表
from django.contrib import admin
# Register your models here.
from .models import User, Book, UserInfo
admin.site.register(User)
admin.site.register(Book)
admin.site.register(UserInfo)
- models.py
from django.db import models
from django.contrib.auth.models import AbstractUser
class UserInfo(AbstractUser):
mobile = models.CharField(max_length=11, default=True)
class Meta:
verbose_name='用户表'
verbose_name_plural='用户表'
def __str__(self):
return self.username
- 创建一个权限组
- 将用户分配到权限组
- 切换到oppo用户只有增加和查看权限
【4】单独给用户增加某个权限
切换到oppo用户有增加和查看权限还有新增的修改和删除功能
Ⅱ 补充
【一】锁定解锁用户接口
# 锁定解锁用户接口--->
-前端传:用户id,lock:True,False
-视图类继承谁?
-不用序列化:APIView
-自动生成路由:ViewSetMixin
-/api/v1/user/3/locked/-->post请求-->请求体{lock:True} # 请求地址携带id
-/api/v1/user/locked/-->post请求-->请求体{user_id:3,lock:True} # 请求地址不携带id
@action(methods=[POST],detail=True)
def locked(self,request,pk)
user=根据pk拿到--》is_activite=True
return Response()
【二】发送短信接口
# 发送短信
-前端:get,mobile-->带在路径中
-视图类继承谁?
-不用序列化:APIView
-自动生成路由:ViewSetMixin
@ction(methods=[POST],detail=False)
def send_sms(self,request):
mobile=requset.query_params.get('mobile')
发送短信方法(mobile)
return Response()
Ⅲ drf部分源码分析
【一】APIView源码
# 问题 继承APIView后
-csrf认证没了
-在执行视图类方法前执行三大认证
-处理全局异常
-包装了新的Request
# 入口
-1 请求来了--->路由匹配成功-->会执行路由后配置的函数内存地址加括号,并且把request对象传入
path('demo01/', demo)-->demo(request)
-2 path('user/', UserView.as_view())---》路由匹配成功就会执行 UserView.as_view()(request)--->最终执行的是:跟请求方式同名的方法
-3 先看 UserView.as_view()-->去APIView中找 as_view()
3.1 @classmethod :类直接调用
3.2 执行完的结果是:
# 执行了父类的as_view--->django的View的as_view-->执行结果是 as_view内部有个 view闭包函数
view = super().as_view(**initkwargs) # django的View的as_view内有个view闭包函数
return csrf_exempt(view) # 去除csrf认证
-4 请求来了,本质执行的是 UserView.as_view()(requets)--->本质是:django的View的as_view内有个view闭包函数去除了csrf认证--->view(request)
-5 读django的--->as_view-->view闭包函数
return self.dispatch(request, *args, **kwargs)
6 本质是:self.dispatch(request, *args, **kwargs)--->APIView的dispatch
7 整个逻辑由:APIView的dispatch决定
def dispatch(self, request, *args, **kwargs):
# 1 包装了新的Request
request = self.initialize_request(request, *args, **kwargs)
# 2 放到了视图类的对象中
self.request = request
try:
# 3 三大认证,依次执行
self.initial(request, *args, **kwargs)
# 4 假设get请求-->request.method.lower()-->get字符串
# http_method_names:列表,带了所有请求方式-->get在里面
if request.method.lower() in self.http_method_names:
# 4.1 self 是 视图类的对象
# 去视图类对象中反射-->get方法
# handler 就是 视图类中跟请求方式同名的方法 内存地址
handler = getattr(self, request.method.lower(),
self.http_method_not_allowed)
else:
handler = self.http_method_not_allowed
# 5 执行了 get(request)--->触发我们写的UserView中得get方法
response = handler(request, *args, **kwargs)
except Exception as exc:
# 6 在执行三大认证或视图类的方法过程中,只要出了异常,都会执行handle_exception
# 全局异常
'''
#1 去配置文件中,找到异常处理函数:
exception_handler = self.get_exception_handler()
# 2 执行异常处理函数
response = exception_handler(exc, context)
'''
response = self.handle_exception(exc)
self.response = self.finalize_response(request, response, *args, **kwargs)
return self.response
# 补充,装饰器用法
#正统写法--->本质是--->被装饰函数=装饰器(被装饰的函数)
@装饰器
def 被装饰的函数():
pass
# 不正统写法
被装饰函数=装饰器(被装饰的函数)
view=csrf_exempt(view)
return view # 两种效果 其实都一样
【二】新的Request对象
# 问题:
-request.data 为什么有 # 看完了
-request._request 就是老的 # 看完了
-request.query_params # 看完了
-用新的,跟老的一样用
# 1 入口:APIView---dispatch--->request = self.initialize_request(request, *args, **kwargs)
# 2 传入了老的reuqest对象
# 传入的request 是老的
def initialize_request(self, request, *args, **kwargs):
# 返回了新的
return Request(
request, #老的
parsers=self.get_parsers(),
authenticators=self.get_authenticators(),
negotiator=self.get_content_negotiator(),
parser_context=parser_context
)
# 3 Request 类的__init__
def __init__(self, request, parsers=None, authenticators=None,
negotiator=None, parser_context=None):
self._request = request # 把老的request放到新的request._request中了
# 4 request.query_params
@property
def query_params(self):
return self._request.GET
# 5 request.data 为什么有--->把所有编码格式的请求体数据,都放在了self._full_data中了-->相当于使用了缓存--->一旦执行过一次
@property
def data(self):
if not _hasattr(self, '_full_data'):
self._load_data_and_files() # 把所有编码格式的请求体数据
return self._full_data
# 6 用新的,跟老的一样用
request.method--->新的里面没有这个属性--->就会触发---—>__getattr__执行
def __getattr__(self, attr):
try:
return getattr(self._request, attr)
except AttributeError:
return self.__getattribute__(attr)
# 补充:对象的 . 拦截
对象.属性/ 方法,调用--->如果存在,直接就用到了,如果不存在--->就会保存
通过重写 __getattr__, 做 . 拦截--->如果不存在,会执行__getattr__
对象.属性--——>如果属性不存在,会触发 __getattr__执行
【三】序列化类之 many=True 作用
# 1 它俩不是同一个对象--->下面两个应该都是 BookSerialzier的对象
serialzier=BookSerialzier(instance=books,many=True)
serialzier=BookSerialzier(instance=book)
# 2 serialzier=BookSerialzier(instance=books,many=True) 是ListSerializer的对象
# 3 serialzier=BookSerialzier(instance=book) 是BookSerialzier的对象
# 4 谁控制对象的生成 --->>>类()--->>先执行__new__创建一个空对象---->>再执行__inti__
-当执行到 __init__的时候,起始对象已经创建出来了
-在它执行,其实先执行了 __new__
# 5 通过重写 __new__控制类的生成
# 6 如果加了many=True--->会执行__new__--->改变对象的生成
serialzier=BookSerialzier(instance=books,many=True)--->执行__new__--->
def __new__(cls, *args, **kwargs):
if kwargs.pop('many', False): # 有many=True
'''
list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
return list_serializer_class(*args, **list_kwargs)
'''
return cls.many_init(*args, **kwargs)
return super().__new__(cls, *args, **kwargs) # 没有many=True-->就是BookSerializer对象
# 7 ListSerializer本质--->[BookSerializer对象1,BookSerializer对象2,BookSerializer对象3]
标签:__,--,self,request,接口,---,models,源码,序列化
From: https://www.cnblogs.com/zyb123/p/18344260