RBAC与JWT

RBAC介绍

RBAC -是基于角色的访问控制(Role-Based Access Control )
用在后台管理系统中,做权限,公司对内使用rbac
对外的网站,权限控制使用三大认证

1 三个表
	-用户表
	-角色表
	-权限表
    
2 6个表(正常是5个表),django的auth,用的就是6表
	-用户表:auth_user
	-角色表:auth_group
	-权限表:auth_permission
	-角色和权限是多对多:auth_group_permissions
	-用户和角色是多对多:auth_user_groups
   
    -用户和权限的多对多表:auth_user_user_permissions

jwt 原理分析

token:
    加密的串:有三段
    	头.荷载(数据).签名
        '''eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ'''
        
    使用bsse64转码
    第一部分我们称它为头部(header),
    第二部分我们称其为载荷(payload, 类似于飞机上承载的物品)
    第三部分是签证(signature).

drf+jwt开发流程

1)用账号密码访问登录接口,登录接口逻辑中调用 签发token 算法,得到token,返回给客户端,客户端自己存到cookies中

2)校验token的算法应该写在认证类中(在认证类中调用),全局配置给认证组件,所有视图类请求,都会进行认证校验,所以请求带了token,就会反解出user对象,在视图类中用request.user就能访问登录的用户

注:登录接口需要做 认证 + 权限 两个局部禁用

base64的使用

# 加码和解码
# base64转码跟语言无关,任何语言都能编码,解码base64

import base64
import json
dic = {'id': 1, 'name': 'abc'}

str_dic=json.dumps(dic)
print(str_dic)

# base64加码
res=base64.b64encode(str_dic.encode('utf-8'))
print(res)

## base64解码
res=base64.b64decode(b'eyJpZCI6IDEsICJuYW1lIjogImxxeiJ9')
print(res)

自动签发token和自动认证

1 借助于djangorestframework-jwt实现
	pip3 install djangorestframework-jwt
2 默认用的是auth的user表
3 不需要写登录功能了
4 也不需要写认证类了
5 djangorestframework-jwt也有配置文件,也有默认配置
	# 默认过期时间是5分钟

    
### 配置文件
import datetime
JWT_AUTH = {
    # 过期时间1天
    'JWT_EXPIRATION_DELTA': datetime.timedelta(days=1),
    # 自定义认证结果:见下方序列化user和自定义response
  	# 如果不自定义,返回的格式是固定的,只有token字段
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'users.utils.jwt_response_payload_handler',  
}


###登录功能
	# 路由(登录功能,djangorestframework-jwt已经写好了登录):
path('login/', obtain_jwt_token),

###限制某个接口必须登录才能用(加载视图类中)
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
authentication_classes = [JSONWebTokenAuthentication,]
permission_classes = [IsAuthenticated,]

##如果只加了JSONWebTokenAuthentication,登录可以用,不登录也可以用
##请求路径(需要在请求头中带)
# Authorization: jwt asdfasdfasfasdfasdtoken串
http://127.0.0.1:8000/api/books/   get请求

jwt自动签发token,自定义响应格式

# 写一个函数
def response_user_login(token, user=None, request=None):
    print(request.method)
    return {
        'status':100,
        'msg':'登录成功',
        'username':user.username,
        'token':token
    }

#在配置文件中配置
JWT_AUTH = {
    'JWT_RESPONSE_PAYLOAD_HANDLER': 'app01.response.response_user_login',
}

jwt手动签发token

自己定义的user表,自己写登录功能

class UserLoginViwe(APIView):

    def post(self, request, *args, **kwargs):
        username = request.data.get('username')
        password = request.data.get('password')

        user = models.User.objects.filter(username=username, password=password).first()
        if user:
            #签发token
            payload = jwt_payload_handler(user)
            token=jwt_encode_handler(payload)
            return Response({'status':100,'msg':'登录成功','token':token})
        else:
            return Response({'status':101,'msg':'用户名或密码错误'})

自定义认证类

import jwt
from rest_framework import exceptions
from rest_framework.authentication import  BaseAuthentication
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework_jwt.settings import api_settings

jwt_decode_handler = api_settings.JWT_DECODE_HANDLER

from app01 import models
class JsonAuthentication(JSONWebTokenAuthentication):
    def authenticate(self, request):
        jwt_value=self.get_jwt_value(request)
        # jwt_value=request.GET.get('token')
        #验证签名,验证是否过期

        try:
            # 得到荷载
            payload = jwt_decode_handler(jwt_value)
            print(payload)
            # user=models.User.objects.filter(id=payload['user_id']).first()
            
            #效率更高一写,不需要查数据库了
            user=models.User(id=payload['user_id'],username=payload['username'])
            # user={'id':payload['user_id'],'username':payload['username']}
        except jwt.ExpiredSignature:
            msg = 'token过期'
            raise exceptions.AuthenticationFailed(msg)
        except jwt.DecodeError:
            msg = '签名错误'
            raise exceptions.AuthenticationFailed(msg)
        except jwt.InvalidTokenError:
            raise exceptions.AuthenticationFailed('反正就不对')

        # 这个咱么不能用,因为它找的是auth的user表,我们是去自己表中查,这个我们需要自己写
        # user = self.authenticate_credentials(payload)
        # models.User.objects.filter(username=)

        return (user, jwt_value)
上一篇:Kubernetes RBAC 详解(转)


下一篇:10、kubernetes之RBAC认证