""" 密码安全服务 提供密码强度检测和弱口令验证功能 """ import re from typing import List, Dict, Tuple from enum import Enum class PasswordStrength(Enum): """密码强度枚举""" WEAK = "weak" MEDIUM = "medium" STRONG = "strong" VERY_STRONG = "very_strong" class PasswordSecurityService: """密码安全服务类""" WEAK_PASSWORDS = [ "123456", "12345678", "123456789", "1234567890", "password", "password123", "admin", "root", "user", "qwerty", "abc123", "letmein", "welcome", "monkey", "dragon", "baseball", "football", "soccer", "trustno1", "master", "hello", "login", "admin123", "password1", "123123", "111111", "888888", "000000", "qwerty123", "admin123", "user123", "pass123", "login123", "welcome1", "admin@123", "root@123", "user@123", "pass@123", "login@123", "123qwe", "qwe123", "abc123", "111222", "333444", "666777", "999888", "123321", "654321", "987654", "123abc", "abc123", "12345a", "a12345", "678901" ] # 常见密码模式 COMMON_PATTERNS = [ r'^\d{6,}$', # 纯数字,6位以上 r'^[a-z]{6,}$', # 纯小写字母,6位以上 r'^[A-Z]{6,}$', # 纯大写字母,6位以上 r'^[a-zA-Z]{6,}$', # 纯字母,6位以上 r'^[a-zA-Z0-9]{6,}$', # 字母+数字,6位以上 r'^.{8,}$', # 任意字符,8位以上 ] @staticmethod def check_password_strength(password: str) -> Tuple[PasswordStrength, List[str]]: """ 检测密码强度 Args: password: 要检测的密码 Returns: Tuple[密码强度, 建议列表] """ suggestions = [] # 1. 检查密码长度 if len(password) < 8: suggestions.append("密码长度至少8位") return PasswordStrength.WEAK, suggestions elif len(password) < 12: suggestions.append("建议密码长度至少12位") elif len(password) >= 16: suggestions.append("密码长度很好") # 2. 检查是否是弱口令 if password.lower() in PasswordSecurityService.WEAK_PASSWORDS: suggestions.append("密码过于常见,容易被猜测") return PasswordStrength.WEAK, suggestions # 3. 检查常见模式 has_common_pattern = False for pattern in PasswordSecurityService.COMMON_PATTERNS: if re.match(pattern, password): has_common_pattern = True break if has_common_pattern: suggestions.append("密码过于简单,建议使用更复杂的组合") # 4. 检查字符类型 has_upper = any(c.isupper() for c in password) has_lower = any(c.islower() for c in password) has_digit = any(c.isdigit() for c in password) has_special = any(not c.isalnum() for c in password) type_count = sum([has_upper, has_lower, has_digit, has_special]) if type_count < 3: suggestions.append("建议包含大小写字母、数字和特殊符号的组合") # 5. 检查连续字符 if PasswordSecurityService._has_sequential_chars(password): suggestions.append("避免使用连续的字符序列") # 6. 检查重复字符 if PasswordSecurityService._has_repeated_chars(password): suggestions.append("避免使用大量重复的字符") # 7. 综合评分 score = 0 # 长度评分 if len(password) >= 16: score += 3 elif len(password) >= 12: score += 2 else: score += 1 # 字符类型评分 score += type_count # 特殊字符评分 if has_special: score += 2 # 综合判断强度 if score >= 8: return PasswordStrength.VERY_STRONG, suggestions elif score >= 6: return PasswordStrength.STRONG, suggestions elif score >= 4: return PasswordStrength.MEDIUM, suggestions else: return PasswordStrength.WEAK, suggestions @staticmethod def is_password_weak(password: str) -> bool: """ 检查密码是否为弱口令 Args: password: 要检查的密码 Returns: True 如果是弱口令,False 否则 """ strength, _ = PasswordSecurityService.check_password_strength(password) return strength == PasswordStrength.WEAK @staticmethod def validate_password_requirements(password: str) -> Tuple[bool, List[str]]: """ 验证密码是否符合基本要求 (长度>=8,且包含大小写、数字、特殊符号中的至少两种) """ errors = [] # 1. 长度检查(保持至少 8 位的基础底线) if len(password) < 8: errors.append("密码长度至少8位") # 2. 统计密码包含的字符种类 has_upper = any(c.isupper() for c in password) has_lower = any(c.islower() for c in password) has_digit = any(c.isdigit() for c in password) has_special = any(not c.isalnum() for c in password) # 算出包含了多少种类型 (True会当作1,False当作0) type_count = sum([has_upper, has_lower, has_digit, has_special]) # 3. 核心修改:四大类中,只要满足 >= 2 种即可 if type_count < 2: errors.append("密码必须包含大写字母、小写字母、数字、特殊符号中的至少两种组合") return len(errors) == 0, errors @staticmethod def _has_sequential_chars(password: str, min_length: int = 3) -> bool: """ 检查是否包含连续字符 Args: password: 密码 min_length: 最小连续长度 Returns: True 如果包含连续字符 """ for i in range(len(password) - min_length + 1): substring = password[i:i+min_length] # 检查数字连续 if substring.isdigit(): if all(ord(substring[j+1]) - ord(substring[j]) == 1 for j in range(len(substring)-1)): return True # 检查字母连续 elif substring.isalpha(): if all(ord(substring[j+1]) - ord(substring[j]) == 1 for j in range(len(substring)-1)): return True return False @staticmethod def _has_repeated_chars(password: str, max_repeats: int = 3) -> bool: """ 检查是否包含重复字符 Args: password: 密码 max_repeats: 最大重复次数 Returns: True 如果包含重复字符 """ for i in range(len(password)): if i + max_repeats <= len(password): char = password[i] if all(password[j] == char for j in range(i, i + max_repeats)): return True return False