hmac_key.py 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. """
  2. HMAC密钥模型
  3. 存储客户端的动态HMAC密钥
  4. """
  5. from sqlalchemy import Column, Integer, String, DateTime, Boolean, Text, Index
  6. from app.models.history_base import HistoryBase
  7. from datetime import datetime
  8. from app.utils.timezone import beijing_now_naive
  9. class HmacKey(HistoryBase):
  10. """HMAC密钥模型
  11. 用于存储客户端的动态HMAC密钥,支持:
  12. - 用户/机器码绑定
  13. - 密钥过期时间管理
  14. - 密钥轮换
  15. """
  16. __tablename__ = 'hmac_keys'
  17. # 基本信息
  18. user_id = Column(Integer, nullable=False, index=True, comment="用户ID")
  19. username = Column(String(64), nullable=False, comment="用户名")
  20. machine_code = Column(String(128), nullable=False, comment="机器码")
  21. # 密钥信息
  22. hmac_key = Column(Text, nullable=False, comment="HMAC密钥")
  23. key_version = Column(Integer, default=1, comment="密钥版本")
  24. # 过期时间
  25. expires_at = Column(DateTime, nullable=False, comment="过期时间")
  26. # 状态
  27. is_active = Column(Boolean, default=True, comment="是否活跃")
  28. # 索引
  29. __table_args__ = (
  30. Index('idx_hmac_key_lookup', 'user_id', 'machine_code', 'is_active'),
  31. Index('idx_hmac_key_expiry', 'expires_at', 'is_active'),
  32. )
  33. def __repr__(self):
  34. return f"<HmacKey(user_id={self.user_id}, username={self.username}, version={self.key_version})>"
  35. def is_expired(self) -> bool:
  36. """检查密钥是否过期"""
  37. return beijing_now_naive() > self.expires_at
  38. def is_valid(self) -> bool:
  39. """检查密钥是否有效"""
  40. return self.is_active and not self.is_expired()
  41. def to_dict(self) -> dict:
  42. """转换为字典"""
  43. return {
  44. "id": self.id,
  45. "user_id": self.user_id,
  46. "username": self.username,
  47. "machine_code": self.machine_code,
  48. "key_version": self.key_version,
  49. "expires_at": self.expires_at.isoformat() if self.expires_at else None,
  50. "is_active": self.is_active,
  51. "created_at": self.created_at.isoformat() if self.created_at else None,
  52. "updated_at": self.updated_at.isoformat() if self.updated_at else None,
  53. }