如何基于请求平台为django-rest-knox设置不同Token TTL?
这问题我之前帮朋友处理过,其实核心就是重写knox的LoginView来动态返回不同的TTL,根据请求头里的平台标识区分就行,具体步骤一步步来:
实现步骤
1. 先在配置文件中定义不同平台的过期时间
把过期时间配置在settings.py里,后续修改更灵活,不用硬编码在业务代码中:
# settings.py from datetime import timedelta # Knox全局默认配置(作为兜底) REST_KNOX = { 'TOKEN_TTL': timedelta(hours=24), } # 移动端与Web端的单独过期时间配置 MOBILE_TOKEN_TTL = timedelta(days=7) # 移动端Token保留7天 WEB_TOKEN_TTL = timedelta(hours=8) # Web端Token保留8小时
2. 自定义登录视图,重写Token过期时间逻辑
在你的用户认证相关app(比如accounts)里新建视图,继承knox的LoginView,重写get_token_ttl方法来根据请求头判断平台:
# accounts/views.py from knox.views import LoginView as KnoxLoginView from rest_framework.authtoken.serializers import AuthTokenSerializer from django.conf import settings class CustomLoginView(KnoxLoginView): serializer_class = AuthTokenSerializer def get_token_ttl(self): # 从请求头获取约定的平台标识字段,比如你用的X-Platform platform = self.request.headers.get('X-Platform', 'web').lower() # 根据平台返回对应过期时间 if platform == 'mobile': return settings.MOBILE_TOKEN_TTL elif platform == 'web': return settings.WEB_TOKEN_TTL # 未知平台返回全局默认值 else: return super().get_token_ttl() # 可选:如果需要在响应里明确告知前端平台和过期时长,可以重写post方法 def post(self, request, format=None): response = super().post(request, format=None) platform = request.headers.get('X-Platform', 'web').lower() ttl = self.get_token_ttl() response.data.update({ 'platform': platform, 'token_expires_in_hours': round(ttl.total_seconds() / 3600, 1) }) return response
3. 替换原有的Knox登录路由
在项目的urls.py里,把默认的knox登录路由替换成我们自定义的视图:
# urls.py from django.urls import path from accounts.views import CustomLoginView urlpatterns = [ # 替换原knox/login路由 path('api/auth/login/', CustomLoginView.as_view(), name='knox_login'), # 其他业务路由... ]
4. 前端请求时携带平台标识请求头
前端在发起登录请求时,需要在请求头中加入约定的字段:
- 移动端请求头:
X-Platform: mobile - Web端请求头:
X-Platform: web
额外场景:注册后自动生成Token
如果你的项目有注册后直接自动登录的需求,不需要走LoginView,可以直接调用Token创建方法时指定过期时间:
from knox.models import Token from django.conf import settings from datetime import datetime def generate_platform_token(user, platform): if platform == 'mobile': expiry = datetime.utcnow() + settings.MOBILE_TOKEN_TTL elif platform == 'web': expiry = datetime.utcnow() + settings.WEB_TOKEN_TTL else: expiry = datetime.utcnow() + settings.REST_KNOX['TOKEN_TTL'] token = Token.objects.create(user=user, expiry=expiry) return token
这样就实现了不同平台登录时Token过期时间的差异化配置,后续要调整时长直接修改settings.py即可,不用改动业务逻辑。
内容的提问来源于stack exchange,提问作者tayyab_fareed
相关产品推荐
相关产品推荐

