给django添加jwt授权

本文详细介绍了如何在Django项目中实现JWT(JSON Web Token)认证流程,包括安装pyjwt库、创建与解析token的方法,以及如何使用装饰器进行权限验证。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

部分内容参考于jwt认证流程

代码实现(持续更新中):Gitee

安装

首先安装pyjwt:

pip3 install pyjwt

使用

创建token

在根目录目录新建util文件夹,新建jwt_auth.py,代码如下:

import jwt
import datetime
from django.conf import settings
from jwt import exceptions

JWT_SALT = settings.SECRET_KEY


def create_token(payload, timeout=20):
    """
    :param payload:  例如:{'user_id':1,'username':'wupeiqi'}用户信息
    :param timeout: token的过期时间,默认20分钟
    :return:
    """
    headers = {
        'typ': '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')
    return result


def parse_payload(token):
    """
    对token进行和发行校验并获取payload
    :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 exceptions.ExpiredSignatureError:
        result['error'] = 'token已失效'
    except jwt.DecodeError:
        result['error'] = 'token认证失败'
    except jwt.InvalidTokenError:
        result['error'] = '非法的token'
    return result

其中JWT_SALT是加密需要用到的盐,我这里取的是Django的默认的SECRET

在你的登录接口使用create_token方法:

# 登录获取token
@require_http_methods(["POST"])
@method_decorator(csrf_exempt, name='dispatch')
def login(request):
    response = {}
    try:
        data = json.loads(request.body)
        user = data.get('username')
        pwd = hashlib.sha1(data.get('password').encode('utf-8')).hexdigest()
        user_obj = Creater.objects.filter(name=user,password=pwd).first()
        if not user_obj:
            response['msg'] = '用户账户或密码错误'
            response['error_num'] = 1
            return JsonResponse(response)
        token = create_token({'username': user})
        user_obj.token = token
        user_obj.save()
        response['token'] = token
        response['msg'] = 'SUCCESS'
        response['error_num'] = 0          
    except Exception as e:
        response['msg'] = str(e)
        response['error_num'] = 1
    return JsonResponse(response)

思路:显示从数据库中获取信息判断用户是否存在,如果存在,执行token = create_token({'username': user}),并将token存入数据库中

解析token

我们需要用到util中的另一个方法parse_payload,我打算用装饰器的方式写,这样可以区分一些路由需要权限与否,首先在根目录新建decorator文件夹,新建jwt.py,代码如下:

from django.conf import settings
from django.http import JsonResponse
from django.contrib.auth import get_user_model
from django.core.exceptions import PermissionDenied
from utils.jwt_auth import parse_payload
  
 
def auth_permission_required():
    def decorator(view_func):
        def _wrapped_view(request, *args, **kwargs):
                try:
                    authorization = request.META.get('HTTP_AUTHORIZATION', '')
                    auth = authorization.split()
                except AttributeError:
                    return JsonResponse({"code": 401, "message": "No authenticate header"})
 
                # 用户通过API获取数据验证流程
                if not auth:
                    return JsonResponse({'error': '未获取到Authorization请求头', 'status': False})
                if auth[0].lower() != 'bearer':
                    return JsonResponse({'error': 'Authorization请求头中认证方式错误', 'status': False})
                if len(auth) == 1:
                    return JsonResponse({'error': "非法Authorization请求头", 'status': False})
                elif len(auth) > 2:
                    return JsonResponse({'error': "非法Authorization请求头", 'status': False})
                token = auth[1]
                result = parse_payload(token)
                if not result['status']:
                    return JsonResponse(result)
 
                return view_func(request, *args, **kwargs)
 
        return _wrapped_view
 
    return decorator

定义了装饰器就可以在view中引入它,在你需要权限验证的地方加上就可以了:

# 创建文章
@require_http_methods(["POST"])
@method_decorator(csrf_exempt, name='dispatch')
@auth_permission_required()
def create_article(request):
    response = {}
    try:
        data = json.loads(request.body)
        category = Category.objects.get(name=data.get('category'))
        name = Creater.objects.get(name=data.get('name'))
        article = Article()
        article.title = data.get('title')
        article.content = data.get('content')
        article.category = category
        article.name = name
        article.save()
        response['msg'] = 'success'
        response['error_num'] = 0
    except Exception as e:
        response['msg'] = str(e)
        response['error_num'] = 1

    return JsonResponse(response)
### 集成JWT认证到Django-Ninja 在现代Web开发中,JSON Web Tokens (JWT) 是一种广泛使用的身份验证机制。对于 `django-ninja` 这一轻量级API框架来说,集成JWT可以显著增强其安全性并简化用户会话管理。 #### 使用PyJWT库实现JWT认证 为了在 `django-ninja` 中启用JWT支持,通常需要依赖于第三方库如 `PyJWT` 或者更高级别的封装工具如 `djangorestframework-simplejwt` 来处理令牌的生成和解析过程[^1]。 以下是具体实现方法: 1. **安装必要的包** 开始之前,请确保已安装所需的Python包: ```bash pip install djangorestframework_simplejwt pyjwt django-ninja ``` 2. **配置settings.py** 将以下内容添加至项目的 `settings.py` 文件中以便激活Simple JWT作为默认的身份验证类之一: ```python INSTALLED_APPS += ['rest_framework', 'rest_framework_simplejwt'] REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_simplejwt.authentication.JWTAuthentication', ) } ``` 3. **创建自定义Auth方案** 创建一个新的文件夹结构用于存放自定义的身份验证逻辑, 并在此基础上扩展原有的功能来适配ninja的需求. ```python import jwt from datetime import timedelta, datetime from ninja.security import HttpBearer SECRET_KEY = "your_secret_key" class CustomAuth(HttpBearer): def authenticate(self, request, token): try: payload = jwt.decode(token, SECRET_KEY, algorithms=['HS256']) return {"id":payload['user_id']} except Exception as e: raise ValueError(f"Invalid Token {e}") auth_scheme = CustomAuth() ``` 4. **保护路由资源** 当前已经具备了基本的能力去校验传入请求中的token有效性,在实际应用过程中可以通过装饰器的形式指定哪些接口需要经过授权才能访问。 ```python from ninja import Router router = Router(auth=auth_scheme) @router.get("/protected/") def protected(request): return f"Protected endpoint - User ID:{request.auth['id']}" ``` 以上步骤展示了如何利用现有的DRF组件快速搭建起一套基于JWT的工作流,并将其无缝嵌入到Ninja API当中[^2]。 ```python import jwt from datetime import timedelta, datetime from ninja.security import HttpBearer SECRET_KEY = "supersecret" class AuthBearer(HttpBearer): def authenticate(self, request, token): try: decoded_payload = jwt.decode( token, SECRET_KEY, algorithms=["HS256"] ) expiration_time = datetime.fromtimestamp(decoded_payload["exp"]) if expiration_time < datetime.utcnow(): return None return {'sub':decoded_payload['sub'], 'role':'admin'} except Exception as ex: print(ex) return None auth_bearer = AuthBearer() @router.post('/login') def login(request, username:str, password:str): # Assume we have some logic here validating credentials... issued_at = int(datetime.now().timestamp()) expires_in_seconds = 86400 # One day validity period. exp = issued_at + expires_in_seconds encoded_jwt = jwt.encode({ 'iss': 'myserver', 'aud': 'webapp', 'iat':issued_at , 'exp': exp, 'sub':username}, key=SECRET_KEY , algorithm='HS256') return {"access_token":encoded_jwt,"expires_in":expires_in_seconds} ``` ### 注意事项 尽管上述代码片段提供了一个简单的解决方案,但在生产环境中部署时还需要考虑更多因素比如刷新策略、黑名单维护以及跨域资源共享等问题[^3]. 相关问题
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值