首页 > 编程语言 >jwt配置文件 drf-jwt源码执行流程 自定义用户实现jwt的签发和认证 simpleui 权限控制(rbac, acl)

jwt配置文件 drf-jwt源码执行流程 自定义用户实现jwt的签发和认证 simpleui 权限控制(rbac, acl)

时间:2023-02-14 18:25:12浏览次数:52  
标签:自定义 配置文件 JWT jwt token user msg payload

昨日内容回顾

# 1 接口文档的编写
    -1 word,md 编写---->存放位置:存放共享文件平台,git上
    -2 第三方的接口文档编写平台
    -3 公司自己开发,使用开源搭建 yapi
    -4 自动生成接口文档
        -django+drf:swagger,coreapi
        -FastAPI:自带自动生成接口文档
        
    -接口文档应该有的东西
    -接口描述
    -请求地址
    -请求方式
    -请求编码格式
    -请求参数(get请求参数,post,put请求参数)
       -参数类型
       -参数是否必填
       -参数解释
    -返回数据
       -json格式示例
       -重点参数解释
    -错误码:写到全局
    
    
# 2 cookie,session,token发展历史
    -会话保持
        -cookie:存在于客户端浏览器的键值对
        -session:存在于服务端的键值对(文件,内存,数据库。。。)
        -token:三部分:头,荷载,签名
                -签发:登录
                -认证:登录后才能访问的接口
                     -认证类
                     -中间件
                     -装饰器
                     -别的位置
                        
# 3 jwt:json web token:前后端认证的机制,token的web形式认证机制

# 4 base64
    -jwt
    -前后端交互:字符串--->base64编码
    -图片:使用base64编码
    
# 5 django+drf如何使用jwt
    -drf-jwt
    
# 6 快速签发
    -配置一条路由--->帮咱们写了登录接口
    
# 7 定制返回格式
    -写一个函数,返回什么,前端就看到什么
    -配置文件中配置
    
# 8 jwt 的认证
    -局部:视图类上
        -认证类---->JSONWebTokenAuthentication
        -权限类---->drf IsAuthenticated
    -全局
    
    -携带token
    	-请求头中
        	Authorization:jwt sadsfasdfasdf.asdfas'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)df.asdfasdf
                
# jwt 配置问题
	-记住的
    	-JWT_RESPONSE_PAYLOAD_HANDLER
        -'JWT_EXPIRATION_DELTA': datetime.timedelta(seconds=300)
    -了解的
    	'JWT_AUTH_HEADER_PREFIX': 'JWT',
        'JWT_SECRET_KEY': settings.SECRET_KEY,
  • drf-jwt源码执行流程(了解)

  • 自定义用户表签发和认证

  • simpleui的使用

  • 权限的控制(acl,rbac)

  • 补充

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

1.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:当前登录用户
            user = serializer.object.get('user') or request.user
            # 签发的token
            token = serializer.object.get('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----》在序列化类的全局钩子中得到的user和签发的token
	-JSONWebTokenSerializer---全局钩子---validate
    	#前端传入,校验过后的数据---》{"username":"lqz","password":"lqz1e2345"}
        def validate(self, attrs):
        credentials = {
            # self.username_field: attrs.get(self.username_field),
            'username':attrs.get('username')
            'password': attrs.get('password')
        }

        if all(credentials.values()):
            # auth 模块,authenticate 可以传入用户名,密码如果用户存在,就返回用户对象,如果不存就是None
            # 正确的用户
            user = authenticate(**credentials)

            if user:
                # 校验用户是否是活跃用户,如果禁用了,不能登录成功
                if not user.is_active:
                    msg = _('User account is disabled.')
                    raise serializers.ValidationError(msg)
				# 荷载----》通过user得到荷载   {id,name,email,exp}
                payload = jwt_payload_handler(user)
				
                return {
                    # jwt_encode_handler通过荷载得到token串
                    'token': jwt_encode_handler(payload),
                    'user': user
                }
            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.')

1.2 认证(认证类)

# JSONWebTokenAuthentication---->父类BaseJSONWebTokenAuthentication----》authenticate方法
    def authenticate(self, request):
        # 前端带在请求头中的token 值
        jwt_value = self.get_jwt_value(request)
        # 如果没有携带token,就不校验了
        if jwt_value is None:
            return None

        try:
            # jwt_value就是token
            # 通过token,得到荷载,中途会出错
            # 出错的原因:
            	-篡改token
                -过期了
                -未知错误
            payload = jwt_decode_handler(jwt_value)
        except jwt.ExpiredSignature:
            msg = _('Signature has expired.')
            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)
# jwt_value = self.get_jwt_value(request)
    def get_jwt_value(self, request):
        # 拿到了前端请求头中传入的 jwt dasdfasdfasdfa
        # auth=[jwt,asdfasdfasdf]
        auth = get_authorization_header(request).split()
        # 'jwt'
        auth_header_prefix = api_settings.JWT_AUTH_HEADER_PREFIX.lower()

        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:
            return None

        if len(auth) == 1:
            msg = _('Invalid Authorization header. No credentials provided.')
            raise exceptions.AuthenticationFailed(msg)
        elif len(auth) > 2:
            msg = _('Invalid Authorization header. Credentials string '
                    'should not contain spaces.')
            raise exceptions.AuthenticationFailed(msg)

        return auth[1]
    
    
       
 # 认证类配置了,如果不传jwt,不会校验,一定配合权限类使用

2 自定义用户表签发和认证

2.1 签发

视图层

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


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': '用户名或密码错误'})

image-20230210220348022

路由

from django.contrib import admin
from django.urls import path
from rest_framework_jwt.views import obtain_jwt_token
from rest_framework.routers import SimpleRouter
from app01.views import UserView

router = SimpleRouter()

router.register('user', UserView, 'user')

urlpatterns = [
    path('admin/', admin.site.urls),
    path('login/', obtain_jwt_token),
]
urlpatterns += router.urls

image-20230210220449962

image-20230210220501882

标签:自定义,配置文件,JWT,jwt,token,user,msg,payload
From: https://www.cnblogs.com/super-xz/p/17120510.html

相关文章

  • pandas里使用map函数并且是自定义函数来实现规则的方式def
      现在我的问题是,有一堆数据,用一些字符串开头,然后换成数字  原本我用的死办法,直接先做字典,然后用字典的内容作为map的映射规则但是由于这些字符太多了,做字典很......
  • vue实现自定义多选按钮
    html部分<div:class=""getSxxClass(item)v-for="(item,index)indata.sxxList":key="index"@click="sxxchangeQuery(item)"></div>js部分constdata=reactive......
  • jQuery custom scrollbarjQuery自定义滚动条
    可以去GitHub上找对应的文件下载,​​https://github.com/mustache/mustache.github.com​​.点击下载压缩包下载完customscrollbar的压缩包,解压,找到里面下张图两个划线......
  • VSCode自定义颜色样式以及背景图片
    ​​"terminal.integrated.fontFamily":"MesloLGMforPowerline"​​看以前的‘美化’太丑了,还是吸血鬼好看"workbench.colorCustomizations":{"activityBar.b......
  • drf入门之自动生成接口、Drf-Jwt及认证类、定制返回格式
    drf入门之自动生成接口、Drf-Jwt及认证类、定制返回格式目录drf入门之自动生成接口、Drf-Jwt及认证类、定制返回格式接口文档使用coreapi自动生成接口文档步骤jwt介绍和原......
  • 自定义数据库项目工程
      各模块功能及依赖总结通过几个例子,来看一下各个模块之间是怎么相互工作的.总结来自NYADB作者,针对声哥的源码进行简单修改。https://qw4990.gitbooks.io/nyadb/c......
  • Android 自定义变化的文本控件ColorChangeView
    实例图说明图/***有颜色过渡变化的textview**@ProjectApp_View*@Packagecom.android.view.colortextview*@authorchenlin*@version1.0*@NoteTODO*//*......
  • Nginx配置文件----- 全局块和event块
    #全局块#指定可以运行nginx服务的用户和用户组,只能在全局块配置#usernobody;#nginx进程,一般数值为cpu核数worker_processes1;#错误日志存放目录#error_loglogs/error.lo......
  • mysql 循环批量建表(表结构相同,表名可以自定义)
    1.情景展示现在有这样一种需求:我需要建两百多张表,这些表的表结构相同,表的名称也是提前拟定好的,必须使用指定的表名;如果使用一个个写SQL语句,那不还得累死,所以,我想到了可不可......
  • opensips将配置文件中的数据库密码加密
    本来没想着给数据库密码加密,结果当时用的数据库密码中有个@符号,opensips在解析数据库连接串的时候,会将@字符后的数据认为是数据库地址,导致一直连接失败。解决方法:1、配置......