password_strength_service.py 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. """
  2. 密码强度检测服务
  3. 提供密码强度评估功能
  4. """
  5. import re
  6. from app.schemas.password_strength_schema import (
  7. PasswordStrengthLevel,
  8. PasswordStrengthResponse
  9. )
  10. class PasswordStrengthService:
  11. """密码强度检测服务"""
  12. @staticmethod
  13. def check_password_strength(password: str) -> PasswordStrengthResponse:
  14. """
  15. 检测密码强度
  16. 强度等级定义:
  17. - 弱(weak): 只有小写字母和数字,或单一类型
  18. - 中(medium): 包含小写字母、数字和特殊符号(至少2种)
  19. - 强(strong): 包含大小写字母、数字和特殊符号(至少3种,且包含大小写)
  20. Args:
  21. password: 待检测的密码
  22. Returns:
  23. PasswordStrengthResponse: 密码强度检测结果
  24. """
  25. if not password:
  26. return PasswordStrengthResponse(
  27. strength=PasswordStrengthLevel.WEAK,
  28. score=0,
  29. suggestions=["密码不能为空"],
  30. meets_requirements=False
  31. )
  32. # 检测各种字符类型
  33. has_lowercase = bool(re.search(r'[a-z]', password))
  34. has_uppercase = bool(re.search(r'[A-Z]', password))
  35. has_digit = bool(re.search(r'\d', password))
  36. has_special = bool(re.search(r'[!@#$%^&*(),.?":{}|<>_\-+=\[\]\\\/;\'`~]', password))
  37. # 计算包含的字符类型数量
  38. type_count = sum([has_lowercase, has_uppercase, has_digit, has_special])
  39. # 密码长度
  40. length = len(password)
  41. # 初始化分数和建议
  42. score = 0
  43. suggestions = []
  44. # 长度评分 (最多40分)
  45. if length >= 12:
  46. score += 40
  47. elif length >= 8:
  48. score += 30
  49. elif length >= 6:
  50. score += 20
  51. else:
  52. score += 10
  53. suggestions.append("密码长度至少需要8个字符")
  54. # 字符类型评分 (最多60分)
  55. score += type_count * 15
  56. # 判断强度等级
  57. strength = PasswordStrengthLevel.WEAK
  58. meets_requirements = length >= 6 and type_count >= 2
  59. if has_uppercase and has_lowercase and has_digit and has_special and length >= 8:
  60. # 强:包含大小写字母、数字、特殊符号
  61. strength = PasswordStrengthLevel.STRONG
  62. if length < 12:
  63. suggestions.append("建议密码长度达到12位以上")
  64. elif type_count >= 2 and length >= 8:
  65. # 中:至少包含2种字符类型
  66. strength = PasswordStrengthLevel.MEDIUM
  67. if not has_uppercase:
  68. suggestions.append("添加大写字母可以提高密码强度")
  69. if not has_special:
  70. suggestions.append("添加特殊符号可以提高密码强度")
  71. if not (has_uppercase and has_lowercase):
  72. suggestions.append("同时包含大小写字母可以提高密码强度")
  73. else:
  74. # 弱:其他情况
  75. strength = PasswordStrengthLevel.WEAK
  76. if not has_lowercase:
  77. suggestions.append("请添加小写字母")
  78. if not has_digit:
  79. suggestions.append("请添加数字")
  80. if not has_special:
  81. suggestions.append("请添加特殊符号(如 !@#$%^&*)")
  82. if not has_uppercase:
  83. suggestions.append("请添加大写字母")
  84. # 检查常见弱密码模式
  85. common_patterns = [
  86. r'12345', r'password', r'qwerty', r'abc', r'111', r'000',
  87. r'admin', r'user', r'test', r'123456'
  88. ]
  89. for pattern in common_patterns:
  90. if re.search(pattern, password.lower()):
  91. score = max(0, score - 20)
  92. suggestions.append("避免使用常见的密码模式")
  93. strength = PasswordStrengthLevel.WEAK
  94. break
  95. # 确保分数在0-100之间
  96. score = max(0, min(100, score))
  97. return PasswordStrengthResponse(
  98. strength=strength,
  99. score=score,
  100. suggestions=suggestions,
  101. meets_requirements=meets_requirements
  102. )