| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210 |
- """
- 密码安全服务
- 提供密码强度检测和弱口令验证功能
- """
- 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
|