You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Django SimpleJWT+django-allauth为社交认证生成个人访问令牌

社交登录用户的个人访问令牌(PAT)实现方案

针对你遇到的CLI工具社交认证瓶颈,完全可以通过实现类似GitHub的个人访问令牌来解决,无需扩展django-simplejwt的登录端点,具体方案如下:

1. 扩展数据库模型

新增PersonalAccessToken模型,用于安全存储用户的令牌信息:

from django.db import models
from django.contrib.auth import get_user_model
from django.contrib.auth.hashers import make_password, check_password
from django.utils import timezone
import secrets

User = get_user_model()

class PersonalAccessToken(models.Model):
    user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="pat_tokens")
    token_hash = models.CharField(max_length=255, unique=True)
    name = models.CharField(max_length=100, help_text="令牌备注,用于区分用途")
    expires_at = models.DateTimeField(null=True, blank=True, help_text="为空则永久有效")
    scopes = models.CharField(max_length=200, blank=True, help_text="权限范围,逗号分隔,如upload_data")
    created_at = models.DateTimeField(auto_now_add=True)

    @classmethod
    def create_token(cls, user, name, expires_at=None, scopes=""):
        # 生成随机明文令牌
        plain_token = secrets.token_urlsafe(32)
        # 哈希后存储,避免明文泄露风险
        token_hash = make_password(plain_token)
        cls.objects.create(
            user=user,
            token_hash=token_hash,
            name=name,
            expires_at=expires_at,
            scopes=scopes
        )
        return plain_token  # 仅返回一次明文令牌,用户需自行保存

    def is_valid(self, plain_token):
        return check_password(plain_token, self.token_hash) and (self.expires_at is None or self.expires_at > timezone.now())

2. 前端实现令牌管理功能

在已登录的用户中心页面添加以下交互:

  • 提供表单让用户输入令牌备注、选择过期时间、勾选权限范围(可选)
  • 点击"生成令牌"后调用后端接口,接收并弹窗展示明文令牌(提示用户立即保存,刷新后不再显示)
  • 展示用户名下所有令牌的列表(仅显示备注、创建时间、过期状态,不显示明文)
  • 支持删除指定令牌的操作

3. 后端新增令牌管理接口

基于Django REST Framework新增一组接口,要求用户已通过JWT认证(前端请求携带Authorization: Bearer <JWT_TOKEN>):

  • 生成令牌接口:POST /api/pat/generate/,接收name、expires_at、scopes参数,调用PersonalAccessToken.create_token生成令牌,返回明文令牌
  • 令牌列表接口:GET /api/pat/list/,返回当前用户的所有令牌基本信息
  • 删除令牌接口:DELETE /api/pat/delete/<int:token_id>/,删除指定ID的令牌

4. CLI工具的认证逻辑

在Python CLI中实现以下流程:

  • 提示用户输入个人访问令牌,或从本地配置文件读取
  • 发起请求时,在请求头中携带Authorization: Bearer <PERSONAL_ACCESS_TOKEN>
  • 后端新增自定义认证后端,验证令牌有效性:
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import PersonalAccessToken

class PATAuthentication(BaseAuthentication):
    def authenticate(self, request):
        auth_header = request.headers.get('Authorization')
        if not auth_header or not auth_header.startswith('Bearer '):
            return None
        
        plain_token = auth_header.split(' ')[1]
        # 遍历用户令牌验证有效性
        for token in PersonalAccessToken.objects.filter(user__is_active=True):
            if token.is_valid(plain_token):
                return (token.user, None)
        
        raise AuthenticationFailed("无效或已过期的个人访问令牌")
  • 在需要CLI访问的视图中,添加authentication_classes = [PATAuthentication, ...](可保留原有JWT认证,兼容两种方式)

5. 关于django-simplejwt的说明

不需要扩展simplejwt的登录端点:

  • simplejwt的核心是生成短期、自包含的会话令牌,用于前后端实时交互;而个人访问令牌是长期、可手动管理的凭证,属于独立的认证体系
  • 单独实现PAT的生成和认证逻辑,不会干扰原有JWT的正常运行,架构更清晰
  • 若强行扩展simplejwt端点,会混淆短期会话令牌和长期访问令牌的职责,增加后续维护成本

注意事项

  • 明文令牌仅在生成时返回一次,后端仅存储哈希值,用户丢失后只能重新生成
  • 建议默认设置令牌过期时间(如30天),避免永久令牌带来的安全风险
  • 权限范围scopes可配合DRF的权限类,实现细粒度的接口访问控制

内容的提问来源于stack exchange,提问作者Phillip

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 12:45:43