Django中如何全局存储外部API返回的JWT令牌直至过期?
在Django中全局存储并复用JWT令牌的实用方案
在Django应用里复用外部API的JWT令牌,核心是存储令牌+自动判断过期,以下是几种适配不同场景的方案:
1. 使用Django内置缓存系统(推荐)
Django缓存支持设置过期时间,刚好匹配JWT的有效期逻辑,是最常用的方案。获取令牌时存入缓存,设置和令牌过期时间一致的超时(可以提前1分钟,避免边缘情况),后续调用API前先从缓存取,取不到再重新请求。
示例代码:
import requests from django.core.cache import cache def get_external_api_token(): # 先从缓存拿令牌 token = cache.get('external_api_jwt_token') if token: return token # 缓存没命中,调用API拿新令牌 auth_url = "https://external-api.com/auth" credentials = {"username": "你的账号", "password": "你的密码"} response = requests.post(auth_url, json=credentials) response.raise_for_status() token_data = response.json() # 提取令牌和过期时间(假设API返回expires_in,单位秒) token = token_data['access_token'] expires_in = token_data.get('expires_in', 3600) # 默认1小时 # 存入缓存,提前1分钟过期,避免令牌刚好用到过期 cache.set('external_api_jwt_token', token, timeout=expires_in - 60) return token # 调用外部API时的用法 def call_external_api(endpoint): token = get_external_api_token() headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"https://external-api.com{endpoint}", headers=headers) # 后续处理响应逻辑...
注意:如果是多进程/多实例部署,别用默认的本地内存缓存,要配置Redis、Memcached这类分布式缓存,保证令牌在所有实例间共享。
2. 自定义单例类存储(单进程场景用)
如果你的应用是单进程部署,用单例类存令牌和过期时间就行,逻辑简单直接。
示例代码:
import requests import time class ExternalAPITokenManager: _instance = None _token = None _expires_at = 0 # 令牌过期的时间戳 def __new__(cls): if cls._instance is None: cls._instance = super().__new__(cls) return cls._instance def get_token(self): current_time = time.time() # 检查令牌是否有效 if self._token and current_time < self._expires_at: return self._token # 重新获取令牌 auth_url = "https://external-api.com/auth" credentials = {"username": "你的账号", "password": "你的密码"} response = requests.post(auth_url, json=credentials) response.raise_for_status() token_data = response.json() self._token = token_data['access_token'] expires_in = token_data.get('expires_in', 3600) self._expires_at = current_time + expires_in - 60 # 提前1分钟过期 return self._token # 全局实例化一次 token_manager = ExternalAPITokenManager() # 调用API时用 def call_external_api(endpoint): token = token_manager.get_token() headers = {"Authorization": f"Bearer {token}"} response = requests.get(f"https://external-api.com{endpoint}", headers=headers) # 处理响应...
注意:多进程部署时,每个进程会有自己的单例实例,令牌无法共享,这种场景别用。
3. 数据库存储(多实例共享+持久化场景用)
如果是多实例部署,且需要令牌在实例间共享,还能持久化,可以存在数据库里,同时记录过期时间。
首先创建模型:
from django.db import models class ExternalAPIToken(models.Model): token = models.CharField(max_length=500) expires_at = models.DateTimeField() created_at = models.DateTimeField(auto_now_add=True) class Meta: verbose_name = "外部API令牌" verbose_name_plural = "外部API令牌"
然后编写获取令牌的逻辑:
import requests from django.utils import timezone from .models import ExternalAPIToken def get_external_api_token(): now = timezone.now() # 找未过期的令牌 token_obj = ExternalAPIToken.objects.filter(expires_at__gt=now).first() if token_obj: return token_obj.token # 重新获取令牌 auth_url = "https://external-api.com/auth" credentials = {"username": "你的账号", "password": "你的密码"} response = requests.post(auth_url, json=credentials) response.raise_for_status() token_data = response.json() token = token_data['access_token'] expires_in = token_data.get('expires_in', 3600) expires_at = now + timezone.timedelta(seconds=expires_in - 60) # 清理过期令牌,再保存新的 ExternalAPIToken.objects.filter(expires_at__lte=now).delete() ExternalAPIToken.objects.create(token=token, expires_at=expires_at) return token
注意:可以加个定时任务定期清理过期令牌,避免数据库冗余。
内容的提问来源于stack exchange,提问作者darkvodka
相关产品推荐
相关产品推荐

