token.py 3.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. """
  2. 本地 Token 验证工具
  3. 用于区分本地生成的 token 和外部系统的 token
  4. """
  5. import jwt
  6. from typing import Optional
  7. from utils.logger import logger
  8. def verify_local_token(token: str) -> Optional[dict]:
  9. """
  10. 验证是否为本地生成的 token
  11. Args:
  12. token: JWT token 字符串
  13. Returns:
  14. 如果是本地 token 返回解码后的数据,否则返回 None
  15. """
  16. if not token:
  17. return None
  18. try:
  19. # 尝试解码 token(不验证签名,只检查格式)
  20. # 本地 token 应该包含特定的字段,如 account, username 等
  21. decoded = jwt.decode(token, options={"verify_signature": False})
  22. # 将解码的 token 打印出来以供调试分析
  23. logger.info(f"[Token验证] 解码后的 Token 负载: {decoded}")
  24. # 检查是否包含本地 token 的特征字段
  25. # 或者包含 user_id, id, sub, sub_id, name 等 (兼容各种其他系统的 token 格式)
  26. if any(k in decoded for k in ["account", "username", "user_id", "id", "sub", "userId", "name", "email", "uid"]):
  27. # 尽可能提取出唯一的用户名/标识
  28. username = (
  29. decoded.get('username') or
  30. decoded.get('account') or
  31. decoded.get('name') or
  32. decoded.get('email') or
  33. f"User_{decoded.get('user_id', decoded.get('id', decoded.get('sub', decoded.get('uid', 'unknown'))))}"
  34. )
  35. # 补全缺失的关键字段,避免后续代码报错
  36. if 'username' not in decoded:
  37. decoded['username'] = username
  38. if 'account' not in decoded:
  39. decoded['account'] = username
  40. # 统一 user_id 字段(兼容 userCode)
  41. if 'userCode' in decoded and 'user_id' not in decoded:
  42. decoded['user_id'] = decoded['userCode']
  43. elif 'user_id' in decoded and 'userCode' not in decoded:
  44. decoded['userCode'] = decoded['user_id']
  45. elif 'id' in decoded:
  46. if 'user_id' not in decoded:
  47. decoded['user_id'] = decoded['id']
  48. if 'userCode' not in decoded:
  49. decoded['userCode'] = decoded['id']
  50. elif 'sub' in decoded:
  51. if 'user_id' not in decoded:
  52. decoded['user_id'] = decoded['sub']
  53. if 'userCode' not in decoded:
  54. decoded['userCode'] = decoded['sub']
  55. logger.info(f"[Token验证] 识别为有效 token: {username}")
  56. return decoded
  57. # 如果以上所有字段都没有,但它是个合法的字典结构,我们也强行给它通过(作为游客)
  58. if isinstance(decoded, dict):
  59. logger.info("[Token验证] 未找到明确用户字段,作为匿名用户处理")
  60. decoded['username'] = "Anonymous"
  61. decoded['account'] = "Anonymous"
  62. decoded['id'] = 0
  63. return decoded
  64. logger.info("[Token验证] 不是本地 token 格式")
  65. return None
  66. except jwt.DecodeError:
  67. logger.info("[Token验证] Token 解码失败,不是有效的 JWT")
  68. return None
  69. except Exception as e:
  70. logger.warning(f"[Token验证] Token 验证异常: {e}")
  71. return None
  72. def is_local_token(token: str) -> bool:
  73. """
  74. 判断是否为本地 token
  75. Args:
  76. token: JWT token 字符串
  77. Returns:
  78. True 表示本地 token,False 表示外部 token
  79. """
  80. return verify_local_token(token) is not None