权限源码分析、认证源码分析、频率源码分析、异常处理、异常处理、jwt介绍和原理、drf-jwt源码执行流程、drf-jwt源码执行流程、权限控制

权限源码分析

写一个权限类 局部使用配置在视图类的 就会执行权限类的permission_classes方法完成权限校验

'''
drf的APIView源码 执行流程:
	1.先匹配路由 APIView中as_view -- 取消csrf校验	
    2.去csrf(view)本质还是view中找as_view -- return self.dispatch(request, *args, **kwargs)
    3.找dispatch 注意这里的self是视图类的对象 所以先从视图类的本身找 -- 在APIView中赵到dispatch 
    4.第497行 self.initial(request, *args, **kwargs)执行三大认证
    5.去到initial中找到:				
    	self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request) 
'''

APIView类的第399行:

    def initial(self, request, *args, **kwargs):
        
        self.format_kwarg = self.get_format_suffix(**kwargs)
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme
        #能够解析的编码 版本控制
        self.perform_authentication(request)
        #认证组件的执行位置
        self.check_permissions(request)
        #权限组件的执行位置【*】
        self.check_throttles(request)
        #频率组件的执行位置
        

APIView第236行:

 def check_permissions(self, request):
        for permission in self.get_permissions():
            #self.get_permissions(): -- 详细见 APIView第274行:get_permissions()-->[CommonPermission(),...()]
            #permission就是CommonPermission()
            if not permission.has_permission(request, self):
                #权限类的对象执行has_permission方法
                #self就是自己写的权限类的has_permission方法的view参数
                #如果配了多个权限 第一个没过 就不会再执行下一个权限类了
                self.permission_denied(
                    request,
                    message=getattr(permission, 'message', None),
                    code=getattr(permission, 'code', None)
                )
                #如果return的是False就会走这里 没有权限 

APIView第274行:

    def get_permissions(self):
        return [permission() for permission in self.permission_classes]
    #self.permission_classes
    #每次从[CommonPermission,...]列表中拿一个加括号执行
    #最终return的是[CommonPermission(),...()]本质是返回了权限类的对象放在了列表中
    '''
    self:视图类的对象
    permission_classes: api_settings.DEFAULT_PERMISSION_CLASSES == 视图类中配的 这一句:permission_classes = [CommonPermission]
    '''

总结:

drf的APIView源码 执行流程:
	1.先匹配路由 APIView中as_view -- 取消csrf校验	
    2.去csrf(view)本质还是view中找as_view -- return self.dispatch(request, *args, **kwargs)
    3.找dispatch 注意这里的self是视图类的对象 所以先从视图类的本身找 -- 在APIView中赵到dispatch 
    4.第497行 self.initial(request, *args, **kwargs)执行三大认证
    5.去到initial中找到:				
    	self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request) 
    6.取出配置再视图类上的权限类 实例化的到对象 一个个执行对象的has_permission方法 如果返回False 就直接结束 不再继续执行 权限就认证通过
    7.如果视图类上不配做权限类:permission_classes = [CommonPermission] 
    会使用配置文件中的 api_settings.DEFAULT_PERMISSION_CLASSES
    优先使用项目配置文件 其次使用drf内置配置文件

认证源码分析

'''
drf的APIView源码 执行流程:
	1.先匹配路由 APIView中as_view -- 取消csrf校验	
    2.去csrf(view)本质还是view中找as_view -- return self.dispatch(request, *args, **kwargs)
    3.找dispatch 注意这里的self是视图类的对象 所以先从视图类的本身找 -- 在APIView中赵到dispatch 
    4.第497行 self.initial(request, *args, **kwargs)执行三大认证
    5.去到initial中找到:				
    	self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request) 
'''

APIView类的第399行:

    def initial(self, request, *args, **kwargs):
        
        self.format_kwarg = self.get_format_suffix(**kwargs)
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme
        #能够解析的编码 版本控制
        self.perform_authentication(request)
        #认证组件的执行位置【*】
        self.check_permissions(request)
        #权限组件的执行位置
        self.check_throttles(request)
        #频率组件的执行位置
        

APIView的第316行

    def perform_authentication(self, request):
        request.user 
        #这是一个方法 包装成了数据属性 request类的user方法

Request类的第219行

@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
    #有执行这个

Request类的第373行

    def _authenticate(self):
        for authenticator in self.authenticators:
            #self.authenticators我们在视图类中配的 authentication_classes = [LoginAuth]
            #request 初始化的时候传入的 self.authenticators详情看Request类的第152行
            try:
                 #返回两个值 第一个是当前用户 第二个是token 也可以返回NOne 会继续执行下一个认证类
                user_auth_tuple = authenticator.authenticate(self)
            except exceptions.APIException:#AuthenticationFailed继承了APIException
                self._not_authenticated() #认证没通过 后面不走
                raise
            if user_auth_tuple is not None:
                self._authenticator = authenticator
                self.user, self.auth = user_auth_tuple
                #self.user=当前登录用户
                #self.auth=token
                #self是新request的对象
                return

        self._not_authenticated()

Request类的第152行

 def __init__(self, request, parsers=None, authenticators=None,
                 negotiator=None, parser_context=None):
        self.authenticators = authenticators or ()
 #什么时候调用__init__ APIView的dispatch的492行

APIView的dispatch的492行

request = self.initialize_request(request, *args, **kwargs)

initialize_request:
    385行:
     return Request(
            authenticators=self.get_authenticators(),
        )
    
get_authenticators:
	return [auth() for auth in self.authentication_classes]
#循环authentication_classes = [LoginAuth]

总结:

1.配置在视图类上的认证类 会在执行视图类方法之前执行 再权限认证之前执行 
2.自己写的认证类可以返回两个值或none
3.后续可以从request.user去除当前登录用户(前提是你要在认证类中返回)

频率源码分析

'''
drf的APIView源码 执行流程:
	1.先匹配路由 APIView中as_view -- 取消csrf校验	
    2.去csrf(view)本质还是view中找as_view -- return self.dispatch(request, *args, **kwargs)
    3.找dispatch 注意这里的self是视图类的对象 所以先从视图类的本身找 -- 在APIView中赵到dispatch 
    4.第497行 self.initial(request, *args, **kwargs)执行三大认证
    5.去到initial中找到:				
    	self.perform_authentication(request)
        self.check_permissions(request)
        self.check_throttles(request) 
'''
    def initial(self, request, *args, **kwargs):
        
        self.format_kwarg = self.get_format_suffix(**kwargs)
        neg = self.perform_content_negotiation(request)
        request.accepted_renderer, request.accepted_media_type = neg
        version, scheme = self.determine_version(request, *args, **kwargs)
        request.version, request.versioning_scheme = version, scheme
        #能够解析的编码 版本控制
        self.perform_authentication(request)
        #认证组件的执行位置【*】
        self.check_permissions(request)
        #权限组件的执行位置
        self.check_throttles(request)
        #频率组件的执行位置
        

APIView的第352行:

    def check_throttles(self, request):
        throttle_durations = []
        for throttle in self.get_throttles():
            #是我们配置在视图类中的throttle_classes = [CommonThrottle]
            #每取出一个频率类对象执行allow_request方法 如果是False 频率超了 不能走了
            if not throttle.allow_request(request, self):
                throttle_durations.append(throttle.wait())
        if throttle_durations:
            # Filter out `None` values which may happen in case of config / rate
            # changes, see #1438
            durations = [
                duration for duration in throttle_durations
                if duration is not None
            ]
            duration = max(durations, default=None)
            self.throttled(request, duration)

总结:

1.写频率类 继承BaseThrottle 
2.重写allow_request方法
3.在内部判断 如果超频就返回False 不超就返回True

异常处理

APIView--->dispatch--->三大认证,视图类的方法,如果出了一场,会被一场捕获,捕获后统一处理

drf 内置了一个函数,只要上面过程出了异常,就会执行这个函数,这个函数只处理的drf的异常

# 写一个函数,内部处理异常,在配置文件中配置一下即可

接口文档

# 前后端分离
	-我们做后端,写接口
    -前端做前端,根据接口写app,pc,小程序
    
    -作为后端来讲,我们很清楚,比如登录接口  /api/v1/login/---->post---->username,password 编码方式json----》返回的格式  {code:100,msg:登录成功}
    
    
    -后端人员,接口写完,一定要写接口文档
    
    
# 接口文档如何编写
	-1 使用word,md 编写接口文档
    -2 使用第三方平台,编写我们的接口文档(非常多)---》收费
    	-https://www.showdoc.com.cn/item/index
    -3 公司自己使用第三方开源的搭建的---》Yapi ---》你如果想自己搭建
    	-https://zhuanlan.zhihu.com/p/366025001 
            
    -4 使用drf编写的接口,可以自动生成接口文档
    	-swagger---》drf-yasg---》官方推荐使用
        -coreapi----》咱们讲
    
    
# 使用coreapi自动生成接口文档步骤
	- 1 安装 
    - 2 配置路由
        from rest_framework.documentation import include_docs_urls
        path('docs/', include_docs_urls(title='xx项目接口文档')),
    -3 在视图类,方法上,写注释即可
    	-在类上加注释
        -在类的方法上加注释
        -在序列化类或表模型的字段上加  help_text,required。。。。
    
    
    -4 配置文件配置
    	REST_FRAMEWORK = {
     		'DEFAULT_SCHEMA_CLASS': 'rest_framework.schemas.coreapi.AutoSchema',

    	}
        
        
   -5 访问地址:http://127.0.0.1:8000/docs
    
    
    
# 接口文档,需要有的东西
	-描述
    -地址
    -请求方式
    -请求编码格式
    -请求数据详解(必填,类型)
    -返回格式案例
    -返回数据字段解释
    -错误码

jwt介绍和原理

# cookie session token 发展史

#Json web token (JWT) 就是web方向token的使用

#JWT的构成 三部分(头 荷载 签名) 每部分用. 分割

头:header
    声明类型 这里是jwt
    声明加密的算法 通常直接使用  HMAC SHA256
    公司信息 

荷载:payload
    存放有效信息的地方
    过期时间
    签发时间
    用户id
    用户名字

签名:signature
	第一部分和第二部分通过密钥+签名的方式得到

jwt开发重点

登录接口 --- 签发token

认证类 --- jwt认证

base64编码和解码

#编码
import base64
import json
dic = {'user_id':1,'username':'lzy'}
dic_str = json.dumps(dic)
#把这个字符串时用base64编码
res = base64.b64encode(dic_str.encode('utf-8'))
print(res)

注意:base64编码后 字符长度一定要是4的倍数 如果不是 使用=补齐(不表示数据)

#解码
res = base64.b64decode('TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ=')

#base64 应用场景
'''
1.jwt 使用了base64
2.网络中传输数据 也会经常使用 base64编码
3.网络传输中 有的图片使用base64
'''

s=''
res = base64.b64encode(s)
with open('a.png','wb')as f:
    f.with(res)

image-20230209171907300

drf-jwt快速使用

django+drf 平台开发jwt这套 有两个模块

	-djangorestframework-jwt  ---》一直可以用
    -djangorestframework-simplejwt---》公司用的多---》希望你们试一下
    -自己封装jwt签发和认证
    
#使用步骤
1.安装
2.登录接口 快速签发token path('login/',obtain_jwt_token)
from rest_framework_jwt.views import obtain_jwt_token
3.postman 向http://127.0.0.1:8000/login/

定制返回格式

基于auth的User表签发token 可以不自己写了 但是登录接口返回的格式只有token 不符合公司规范 可以自己自定义添加

#使用步骤
	1.建一个py文件 写一个函数def jwt_response_payload_handler(token, user=None, request=None):
    return {
        'code':100,
        'msg':'登陆成功',
        'token':token,
        'username':user.username,

    }
from rest_framework_jwt.views import jwt_response_payload_handler 用这个函数

	2.配置一下settings
    JWT_AUTH = {
    	'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.utils.jwt_response_payload_handler',  
	}
    3.测试

补充

1.django 的 auth user表密码是加密的 同样的密码密文也都不一样
	- 每次加密 都随机生成一个盐 把盐拼在加密后的串中
    eg:
    	pbkdf2_sha256$150000$CptHucCygPZv$Z4HP93MR9qj6mNDKeN4ew9ZrKWceoi5KJ
    明文:
    	123
    加盐:
    	CptHucCygPZv
        
2.自定义用户表  生成密码用密文


3.用户密码忘了怎么办
	-新增一个用户 把他的密文复制过去
    
4.双token认证
	-

drf-jwt源码执行流程(了解)

1.签发(登录)

#登录接口路由匹配成功 执行obtain_jwt_token()--post请求--ObtainJSONWebToken的post方法 
	path('login/',obtain_jwt_token)
    
#ObtainJSONWebToken的post方法继承APIView 
	    def post(self, request, *args, **kwargs):
        serializer = self.get_serializer(data=request.data)
        #序列化得到序列化类
        if serializer.is_valid():
        #做校验 校验自己 局部钩子 全局钩子
            user = serializer.object.get('user') or request.user
        #user:当前登录用户 
            token = serializer.object.get('token')
        #token:签发的token
            response_data = jwt_response_payload_handler(token, user, request)
        #构造返回格式 可以自己定制 
            response = Response(response_data)
            if api_settings.JWT_AUTH_COOKIE:
                expiration = (datetime.utcnow() +
                              api_settings.JWT_EXPIRATION_DELTA)
                response.set_cookie(api_settings.JWT_AUTH_COOKIE,
                                    token,
                                    expires=expiration,
                                    httponly=True)
            return response
        	#返回自己定制的返回格式

        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
    
    

如何得到user 如何签发token

class RefreshJSONWebTokenSerializer(VerificationBaseSerializer):
     def validate(self, attrs):
            #前端传入校验过后的数据  {"username":"lzy","password":"123"}
        credentials = {
            #'username':attrs.get('username') 'password':attrs.get('password')
            #获取用户名和密码
            self.username_field: attrs.get(self.username_field),
            'password': attrs.get('password')
        }
		
        if all(credentials.values()):
            user = authenticate(**credentials)
            #auth模块 authenticate可以传用户名和密码 如果用户名存在 就返回用户对象 如果不存在就是None

            if user:
                if not user.is_active:
                    #校验用户是否是活跃用户 如果禁用了不能登录
                    msg = _('User account is disabled.')
                    raise serializers.ValidationError(msg)

                payload = jwt_payload_handler(user)
				#荷载 通过user生成荷载
                return {
                    'token': jwt_encode_handler(payload),
                    'user': user
                    #jwt_encode_handler通过荷载得到token串
                }
            else:
                msg = _('Unable to log in with provided credentials.')
                raise serializers.ValidationError(msg)
        else:
            msg = _('Must include "{username_field}" and "password".')
            msg = msg.format(username_field=self.username_field)
            raise serializers.ValidationError(msg)

重点:

1.通过user得到荷载: payload = jwt_payload_handler(user)

2.通过荷载签发token:jwt_encode_handler(payload)

了解:

翻译函数_ 只要做了国际化 放英文 会翻译成该国语言(在配置文件中配置)

from django.utils.translation import ugettext as _
	msg = _('Unable to log in with provided credentials.')

2.认证

#JSONWebTokenAuthentication  去他的父类找 --BaseJSONWebTokenAuthentication -- authenticate方法 

    def authenticate(self, request):
        jwt_value = self.get_jwt_value(request)
        #前端带在请求头中的token值
        if jwt_value is None:
            return None
        #如果没有token值 返回 none 就不进行认证 所以 必须结合权限类一起使用
		
        try:
            payload = jwt_decode_handler(jwt_value)
            #通过token得到荷载  中途会出错
            #出错的原因:篡改token 过期 未知错误
        except jwt.ExpiredSignature:
            msg = _('Signaturexpired.')
            raise exceptions.AuthenticationFailed(msg)
        except jwt.DecodeError:
            msg = _('Error decoding signature.')
            raise exceptions.AuthenticationFailed(msg)
        except jwt.InvalidTokenError:
            raise exceptions.AuthenticationFailed()
		#如果一点错误都没有 就说明token是可以被信任的 payload就可以使用 通过payload得到当前登录用户 
        user = self.authenticate_credentials(payload)
		#返回当前登录的用户 和token值
        return (user, jwt_value)
#token怎么取出来的?
#jwt_value = self.get_jwt_value(request)
    
    def get_jwt_value(self, request):
        auth = get_authorization_header(request).split()
        #拿到了前端请求头中传入的数据 jwt 68767864670
        #auth = [jwt,7467]
        
        auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower()
		#'jwt'
        if not auth:
            #如果请求头里没带 他就去cookie里取
            if api_settings.JWT_AUTH_COOKIE:
                return request.COOKIES.get(api_settings.JWT_AUTH_COOKIE)
            return None

        if smart_text(auth[0].lower()) != auth_header_prefix:
            #判断auth = [jwt,7467]第一个数 =不=auth_header_prefix
            return None

        if len(auth) == 1:
            msg = _('Invalid Authorization header. No credentials provided.')
            raise exceptions.AuthenticationFailed(msg)
            #判断auth的长度等于1就不合法了
        elif len(auth) > 2:
            msg = _('Invalid Authorization header. Credentials string '
                    'should not contain spaces.')
            raise exceptions.AuthenticationFailed(msg)
			
        return auth[1]
    	# = 2 就可以 取出auth里面索引为1的数值 就是token
        
        
        
        
#认证类配置了 如果不传jwt 不会校验 一定要配合权限使用

自定义用户表签发

from rest_framework_jwt.settings import api_settings

jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER
jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER

from rest_framework.viewsets import ViewSet
from rest_framework.decorators import action
from rest_framework.response import Response
from .models import UserInfo
from .authentication import JsonWebTokenAuthentication


class UserView(ViewSet):
    @action(methods=['POST'], detail=False)
    def login(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')
        user = UserInfo.objects.filter(username=username, password=password).first()
        if user:
            # 登录成功,签发token
            # 通过user得到payload
            payload = jwt_payload_handler(user)
            # 通过payload得到token
            token = jwt_encode_handler(payload)
            return Response({'code': 1000, 'msg': '登录成功', 'token': token})
        else:
            return Response({'code': 1001, 'msg': '用户名或密码错误'})

自定义用户表认证

from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
import jwt
from .models import UserInfo
from rest_framework_jwt.settings import api_settings

jwt_decode_handler = api_settings.JWT_DECODE_HANDLER


class JsonWebTokenAuthentication(BaseAuthentication):
    def authenticate(self, request):
        # 取出token----》请求头中,就叫token
        token = request.META.get('HTTP_TOKEN')
        if token:
            try:
                payload = jwt_decode_handler(token)
                # 得到当前登录用户----》
                user = UserInfo.objects.get(pk=payload.get('user_id'))
                # 只要访问一次需要登录的接口,就会去UserInfo表中查一次用户---》优化
                # user=UserInfo(id=payload.get('user_id'),username=payload.get('username'))
                # user={'id':payload.get('user_id')}

                return user, token
            except jwt.ExpiredSignature:
                raise AuthenticationFailed('token过期')
            except jwt.DecodeError:
                raise AuthenticationFailed('token认证失败')

            except jwt.InvalidTokenError:
                raise AuthenticationFailed('token无效')
            except Exception as e:
                raise AuthenticationFailed('未知异常')

        raise AuthenticationFailed('token没有传,认证失败')

simpleui的使用

django的ahmin界面不好看 我们可以使用 simpleui

1.使用步骤

1.安装:
	pip install django-simpleui

2.在app中注册(官方文档)

3.调整左侧导航栏
	-menu_display对应menus name
    -如果是项目的app,就menus写app
    -菜单可以多级,一般咱们内部app,都是一级
    -可以增加除咱们app外的其它链接---》如果是外部链接,直接写地址,如果是内部链接,跟之前前后端混合项目一样的写法:咱们的案例---》show 的路由
SIMPLEUI_CONFIG = {
    'system_keep': False,
    'menu_display': ['图书管理', '权限认证', '张红测试'],  # 开启排序和过滤功能, 不填此字段为默认排序和全部显示, 空列表[] 为全部不显示.
    'dynamic': True,  # 设置是否开启动态菜单, 默认为False. 如果开启, 则会在每次用户登陆时动态展示菜单内容
    'menus': [
        {
            'name': '图书管理',
            'app': 'app01',
            'icon': 'fas fa-code',
            'models': [
                {
                    'name': '图书',
                    'icon': 'fa fa-user',
                    'url': 'app01/book/'
                },
                {
                    'name': '出版社',
                    'icon': 'fa fa-user',
                    'url': 'app01/publisssh/'
                },
                {
                    'name': '作者',
                    'icon': 'fa fa-user',
                    'url': 'app01/author/'
                },
                {
                    'name': '作者详情',
                    'icon': 'fa fa-user',
                    'url': 'app01/authordetail/'
                },
            ]
        },
        {
            'app': 'auth',
            'name': '权限认证',
            'icon': 'fas fa-user-shield',
            'models': [
                {
                    'name': '用户',
                    'icon': 'fa fa-user',
                    'url': 'auth/user/'
                },
                {
                    'name': '组',
                    'icon': 'fa fa-user',
                    'url': 'auth/group/'
                },
            ]
        },
        {

            'name': '张红测试',
            'icon': 'fa fa-file',
            'models': [
                {
                    'name': 'Baidu',
                    'icon': 'far fa-surprise',
                    # 第三级菜单 ,
                    'models': [
                        {
                            'name': '爱奇艺',
                            'url': 'https://www.iqiyi.com/dianshiju/'
                            # 第四级就不支持了,element只支持了3级
                        }, {
                            'name': '百度问答',
                            'icon': 'far fa-surprise',
                            'url': 'https://zhidao.baidu.com/'
                        }
                    ]
                },
                {
                    'name': '大屏展示',
                    'url': '/show/',
                    'icon': 'fab fa-github'
                }]
        }
    ]
}
4.内部app,图书管理系统某个链接要展示的字段---》在admin.py 中----》自定义按钮
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
    list_display = ('nid', 'name', 'price', 'publish_date', 'publish')

    # 增加自定义按钮
    actions = ['custom_button']

    def custom_button(self, request, queryset):
        print(queryset)

    custom_button.confirm = '你是否执意要点击这个按钮?'
    # 显示的文本,与django admin一致
    custom_button.short_description = '测试按钮'
    # icon,参考element-ui icon与https://fontawesome.com
    # custom_button.icon = 'fas fa-audio-description'
    # # 指定element-ui的按钮类型,参考https://element.eleme.cn/#/zh-CN/component/button
    custom_button.type = 'danger'
    # # 给按钮追加自定义的颜色
    # custom_button.style = 'color:black;'
    
    
5. app名字显示中文,字段名字显示中文
	-新增,查看修改展示中文,在表模型的字段上加:verbose_name='图书名字',help_text='这里填图书名'
	-app名字中文:apps.py---》verbose_name = '图书管理系统'

    
6. 其它配置项
	SIMPLEUI_LOGIN_PARTICLES = False  #登录页面动态效果
    SIMPLEUI_LOGO = 'https://avatars2.githubusercontent.com/u/13655483?s=60&v=4'#图标替换
    SIMPLEUI_HOME_INFO = False  #首页右侧github提示
    SIMPLEUI_HOME_QUICK = False #快捷操作
    SIMPLEUI_HOME_ACTION = False # 动作

大屏展示

#gitee
https://search.gitee.com/?skin=rec&type=repository&q=%E5%B1%95%E7%A4%BA%E5%A4%A7%E5%B1%8F

权限控制


```python
# 公司内部项目
	-rbac:是基于角色的访问控制(Role-Based Access Control )在 RBAC  中,权限与角色相关联,用户通过成为适当角色的成员而得到这些角色的权限。这就极大地简化了权限的管理。这样管理都是层级相互依赖的,权限赋予给角色,而把角色又赋予用户,这样的权限设计很清楚,管理起来很方便
    
    -用户表:用户和角色多对多关系,
    -角色表
    	-一个角色可能有多个权限----》
        	-开发角色:拉取代码,上传代码
        	-财务角色:开工资,招人,开除人
            -
    -权限表:角色和权限是多多多
    	-拉取代码
        -上传代码
        -部署项目
        -开工资
        -招人
        -开除人
        -
    -通过5张表完成rbac控制:用户表,角色表,权限表, 用户角色中间表, 角色权限中间表
    -如果某个人,属于财务角色,单只想要拉取代码权限,不要上传代码权限
    -通过6张表:django的admin----》后台管理就是使用这套权限认证
    	用户表,
        角色表,
        权限表, 
        用户角色中间表, 
        角色权限中间表
        用户和权限中间表
# 互联网项目
	-acl:Access Control List 访问控制列表,权限放在列表中
    -权限:权限表----》 发视频,评论,开直播
    -用户表:用户和权限是一对多
    
    张三:[发视频,]
    李四:[发视频,评论,开直播]
    
    
    
    
    
 
# 演示了 django-admin 的权限控制
	-授予lqz 某个组
    -单独授予权限
    
    
# django -auth--6张表
	auth_user   用户表
	auth_group  角色表,组表
    auth_permission  权限表
    -----------
    auth_user_groups   用户和角色中间表
    auth_group_permissions  角色和权限中间表
	-------------
    auth_user_user_permissions  用户和权限中间表
    
    
    
# java:若依
# go :gin-vue-admin
# python :django-vue-admin
posted @ 2023-02-12 18:31  李李大冒险  阅读(41)  评论(0编辑  收藏  举报
  1. 1 不可撤销
  2. 2 小年兽 程嘉敏
  3. 3 迷人的危险3 FAFA
  4. 4 山楂树之恋 程佳佳
  5. 5 summertime cinnamons / evening cinema
  6. 6 不谓侠(Cover 萧忆情Alex) CRITTY
  7. 7 神武醉相思(翻自 优我女团) 双笙(陈元汐)
  8. 8 空山新雨后 音阙诗听 / 锦零
  9. 9 Wonderful U (Demo Version) AGA
  10. 10 广寒宫 丸子呦
  11. 11 陪我看日出 回音哥
  12. 12 春夏秋冬的你 王宇良
  13. 13 世界が终わるまでは… WANDS
  14. 14 多想在平庸的生活拥抱你 隔壁老樊
  15. 15 千禧 徐秉龙
  16. 16 我的一个道姑朋友 双笙(陈元汐)
  17. 17 大鱼 (Cover 周深) 双笙(陈元汐)
  18. 18 霜雪千年(Cover 洛天依 / 乐正绫) 双笙(陈元汐) / 封茗囧菌
  19. 19 云烟成雨(翻自 房东的猫) 周玥
  20. 20 情深深雨濛濛 杨胖雨
  21. 21 Five Hundred Miles Justin Timberlake / Carey Mulligan / Stark Sands
  22. 22 斑马斑马 房东的猫
  23. 23 See You Again Wiz Khalifa / Charlie Puth
  24. 24 Faded Alan Walker
  25. 25 Natural J.Fla
  26. 26 New Soul Vox Angeli
  27. 27 ハレハレヤ(朗朗晴天)(翻自 v flower) 猫瑾
  28. 28 像鱼 王贰浪
  29. 29 Bye Bye Bye Lovestoned
  30. 30 Blame You 眠 / Lopu$
  31. 31 Believer J.Fla
  32. 32 书信 戴羽彤
  33. 33 柴 鱼 の c a l l i n g【已售】 幸子小姐拜托了
  34. 34 夜空中最亮的星(翻自 逃跑计划) 戴羽彤
  35. 35 慢慢喜欢你 LIve版 戴羽彤
  36. 36 病变 戴羽彤
  37. 37 那女孩对我说 (完整版) Uu
  38. 38 绿色 陈雪凝
  39. 39 月牙湾 LIve版 戴羽彤
像鱼 - 王贰浪
00:00 / 04:45
An audio error has occurred, player will skip forward in 2 seconds.

作词 : 周有才

作曲 : 周有才

这是一首简单的歌

没有什么独特

试着代入我的心事

它那么幼稚

像个顽皮的孩子

多么可笑的心事

只剩我还在坚持

谁能看透我的眼睛

让我能够不再失明

我要记住你的样子

像鱼记住水的拥抱

像云在天空中停靠

夜晚的来到

也不会忘了阳光的温暖

我要忘了你的样子

像鱼忘了海的味道

放下所有梦和烦恼

却放不下回忆的乞讨

多么可笑的心事

只剩我还在坚持

谁能看透我的眼睛

让我能够不再失明

记住你的样子

像鱼记住水的拥抱

像云在天空中停靠

夜晚的来到

也不会忘了阳光的温暖

我要忘了你的样子

像鱼忘了海的味道

放下所有梦和烦恼

却放不下回忆的乞讨

只剩自己就好