返回

Django jwt token验证

发布时间:2022-11-23 15:53:03 296
# python# django# 数据库# 数据# 信息

Django 自带的登录验证是使用session 验证的,适用于web;今天来个通过token验证的,适用于web + app

import jwt
import datetime
from jwt import exceptions
from rest_framework.authentication import BaseAuthentication
from rest_framework import exceptions
import logging

log = logging.getLogger("log")

JWT_SALT = "ds()udsjo@jlsdosjf)wjd_#(#)$"


def create_token(payload, timeout=600):
# 声明类型,声明加密算法
headers = {
"type": "jwt",
"alg": "HS256"
}
# 设置过期时间
payload['exp'] = datetime.datetime.utcnow() + datetime.timedelta(minutes=timeout)
result = jwt.encode(payload=payload, key=JWT_SALT, algorithm="HS256", headers=headers).decode("utf-8")
# 返回加密结果 注意添加jwt前缀,解密会用到
return "jwt " + result


def parse_payload(token):
"""
用于解密
:param token:
:return:
"""
result = {"status": False, "data": None, "error": None}
try:
# 进行解密
verified_payload = jwt.decode(token, JWT_SALT, True)
result["status"] = True
result['data'] = verified_payload
except jwt.ExpiredSignatureError:
result['error'] = 'token已失效'
log.error("ExpiredSignatureError")
except jwt.DecodeError:
result['error'] = 'token认证失败'
except jwt.InvalidTokenError:
result['error'] = '非法的token'
return result


class JwtQueryParamAuthentication(BaseAuthentication):
"""
用户需要在url中通过参数进行传输token,例如:
http://www.pythonav.com?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzM1NTU1NzksInVzZXJuYW1lIjoid3VwZWlxaSIsInVzZXJfaWQiOjF9.xj-7qSts6Yg5Ui55-aUOHJS4KSaeLq5weXMui2IIEJU
"""

def authenticate(self, request):
# 从url上获取jwt token
log.info("进入token校验")
try:
token = request.META.get("HTTP_TOKEN")
except Exception as e:
log.error("获取token失败, %s" % e)
print("token 异常了")
raise
payload = parse_payload(token)
if not payload['status']:
raise exceptions.AuthenticationFailed(payload)
log.info("校验完成")
# 如果想要request.user等于用户对象,此处可以根据payload去数据库中获取用户对象。
return (payload, token)


class JwtAuthorizationAuthentication(BaseAuthentication):
"""
用户需要通过请求头的方式来进行传输token,例如:
Authorization:jwt eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1NzM1NTU1NzksInVzZXJuYW1lIjoid3VwZWlxaSIsInVzZXJfaWQiOjF9.xj-7qSts6Yg5Ui55-aUOHJS4KSaeLq5weXMui2IIEJU
"""

def authenticate(self, request):
# 非登录页面需要校验token,从头信息拿去JWT Token
authorization = request.META.get('HTTP_AUTHORIZATION', '')
auth = authorization.split()
if not auth:
raise exceptions.AuthenticationFailed({'error': '未获取到Authorization请求头', 'status': False})
if auth[0].lower() != 'jwt':
raise exceptions.AuthenticationFailed({'error': 'Authorization请求头中认证方式错误', 'status': False})

if len(auth) == 1:
raise exceptions.AuthenticationFailed({'error': "非法Authorization请求头", 'status': False})
elif len(auth) > 2:
raise exceptions.AuthenticationFailed({'error': "非法Authorization请求头", 'status': False})

token = auth[1]
result = parse_payload(token)
if not result['status']:
raise exceptions.AuthenticationFailed(result)

# 如果想要request.user等于用户对象,此处可以根据payload去数据库中获取用户对象。
print("验证通过")
return (result, token)

上面的代码块分别定义了加密解密方法

from django.utils.deprecation import MiddlewareMixin
from common.jwt_auth import JwtAuthorizationAuthentication
from django.http.response import JsonResponse
from common.enums import StatusCodeEnum
import logging

log = logging.getLogger("log")

class AuthMiddlewareMixin(MiddlewareMixin):
   "定义中间件"
def process_view(self, request, view_func, view_args, view_kwargs):
# process_view 的参数是固定的,不能少一个
# 排除登录和注册接口
skip_urls = ["/user/login", "/user/registration"]
if request.path in skip_urls:
print("跳过")
log.info("跳过")
return
# 如果非登录接口,校验token,不通过返回特殊code
try:
JwtAuthorizationAuthentication().authenticate(request)
except Exception as e:
log.error(str(e))
# 返回格式自行定义
return JsonResponse({"code": StatusCodeEnum.TOKEN_ERR_CODE.code, "msg": StatusCodeEnum.TOKEN_ERR_CODE.msg})

最后别忘记在setting 文件添加中间件

Django jwt token验证_d3

 

 

 

 

 

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像
精选文章
thumb 中国研究员首次曝光美国国安局顶级后门—“方程式组织”
thumb 俄乌线上战争,网络攻击弥漫着数字硝烟
thumb 从网络安全角度了解俄罗斯入侵乌克兰的相关事件时间线
下一篇
UE4 蓝图查找Actor和Actor标签 2022-11-23 15:06:18