""" 认证管理器模块 确保通信安全 """ import time import hashlib import secrets import hmac from typing import Dict, Any, List, Optional class AuthManager: """ 认证管理器 确保通信安全 """ def __init__(self, plugin): """ 初始化认证管理器 Args: plugin: 实时通信插件实例 """ self.plugin = plugin self.enabled = False self.initialized = False # 认证配置 self.auth_config = { "enable_authentication": True, "auth_timeout": 30.0, "enable_token_auth": True, "enable_password_auth": True, "token_lifetime": 86400, # 24小时 "enable_session_management": True, "session_timeout": 3600, # 1小时 "enable_two_factor_auth": False, "max_login_attempts": 5, "login_lockout_duration": 900, # 15分钟 "enable_ip_filtering": True, "enable_audit_logging": True } # 认证状态 self.auth_state = { "active_sessions": 0, "total_authentications": 0, "successful_authentications": 0, "failed_authentications": 0 } # 认证存储 self.sessions = {} self.tokens = {} self.login_attempts = {} self.blocked_ips = {} # 认证统计 self.auth_stats = { "tokens_generated": 0, "sessions_created": 0, "sessions_expired": 0, "users_banned": 0, "auth_errors": 0 } # 密钥管理 self.secret_key = self._generate_secret_key() # 回调函数 self.auth_callbacks = { "auth_success": [], "auth_failed": [], "session_created": [], "session_expired": [], "user_banned": [], "auth_error": [] } # 时间戳记录 self.last_session_cleanup = 0.0 self.last_auth_event = 0.0 print("✓ 认证管理器已创建") def initialize(self) -> bool: """ 初始化认证管理器 Returns: 是否初始化成功 """ try: print("正在初始化认证管理器...") # 生成密钥 self.secret_key = self._generate_secret_key() self.initialized = True print("✓ 认证管理器初始化完成") return True except Exception as e: print(f"✗ 认证管理器初始化失败: {e}") self.auth_stats["auth_errors"] += 1 import traceback traceback.print_exc() return False def _generate_secret_key(self) -> str: """ 生成密钥 Returns: 生成的密钥 """ try: return secrets.token_hex(32) except Exception as e: print(f"✗ 密钥生成失败: {e}") # 使用默认密钥(仅用于开发环境) return "default_secret_key_for_development_purposes_only" def enable(self) -> bool: """ 启用认证管理器 Returns: 是否启用成功 """ try: if not self.initialized: print("✗ 认证管理器未初始化") return False self.enabled = True print("✓ 认证管理器已启用") return True except Exception as e: print(f"✗ 认证管理器启用失败: {e}") self.auth_stats["auth_errors"] += 1 import traceback traceback.print_exc() return False def disable(self): """禁用认证管理器""" try: self.enabled = False # 清理会话和令牌 self.sessions.clear() self.tokens.clear() print("✓ 认证管理器已禁用") except Exception as e: print(f"✗ 认证管理器禁用失败: {e}") self.auth_stats["auth_errors"] += 1 import traceback traceback.print_exc() def finalize(self): """清理认证管理器资源""" try: # 禁用认证管理器 if self.enabled: self.disable() # 清理回调 self.auth_callbacks.clear() self.initialized = False print("✓ 认证管理器资源已清理") except Exception as e: print(f"✗ 认证管理器资源清理失败: {e}") import traceback traceback.print_exc() def update(self, dt: float): """ 更新认证管理器状态 Args: dt: 时间增量(秒) """ try: if not self.enabled: return current_time = time.time() # 定期清理过期会话 if current_time - self.last_session_cleanup > 300: # 每5分钟清理一次 self._cleanup_expired_sessions(current_time) self.last_session_cleanup = current_time # 定期清理登录尝试记录 self._cleanup_login_attempts(current_time) self.last_auth_event = current_time except Exception as e: print(f"✗ 认证管理器更新失败: {e}") self.auth_stats["auth_errors"] += 1 import traceback traceback.print_exc() def _cleanup_expired_sessions(self, current_time: float): """清理过期会话""" try: expired_sessions = [] for session_id, session_data in self.sessions.items(): if current_time - session_data["login_time"] > self.auth_config["session_timeout"]: expired_sessions.append(session_id) for session_id in expired_sessions: del self.sessions[session_id] self.auth_state["active_sessions"] -= 1 self.auth_stats["sessions_expired"] += 1 # 触发会话过期回调 self._trigger_auth_callback("session_expired", { "session_id": session_id, "timestamp": current_time }) except Exception as e: print(f"✗ 过期会话清理失败: {e}") self.auth_stats["auth_errors"] += 1 def _cleanup_login_attempts(self, current_time: float): """清理登录尝试记录""" try: expired_attempts = [] for ip_address, attempt_data in self.login_attempts.items(): if current_time - attempt_data["last_attempt"] > self.auth_config["login_lockout_duration"]: expired_attempts.append(ip_address) for ip_address in expired_attempts: del self.login_attempts[ip_address] except Exception as e: print(f"✗ 登录尝试记录清理失败: {e}") self.auth_stats["auth_errors"] += 1 def authenticate_client(self, client_id: str, auth_data: Dict[str, Any]) -> bool: """ 认证客户端 Args: client_id: 客户端ID auth_data: 认证数据 Returns: 是否认证成功 """ try: if not self.enabled or not self.auth_config["enable_authentication"]: # 如果未启用认证,直接通过 return True # 检查IP是否被阻止 client_ip = auth_data.get("client_ip", "") if self._is_ip_blocked(client_ip): self.auth_stats["failed_authentications"] += 1 return False # 检查登录尝试次数 if self._is_login_blocked(client_ip): self.auth_stats["failed_authentications"] += 1 return False # 执行认证 auth_result = self._perform_authentication(client_id, auth_data) if auth_result: self.auth_state["successful_authentications"] += 1 self.auth_state["total_authentications"] += 1 # 触发认证成功回调 self._trigger_auth_callback("auth_success", { "client_id": client_id, "auth_data": auth_data, "timestamp": time.time() }) # 记录审计日志 if self.auth_config["enable_audit_logging"]: self._log_auth_event("auth_success", client_id, client_ip) else: self.auth_state["failed_authentications"] += 1 self.auth_state["total_authentications"] += 1 # 记录失败的登录尝试 self._record_failed_login(client_ip) # 触发认证失败回调 self._trigger_auth_callback("auth_failed", { "client_id": client_id, "auth_data": auth_data, "timestamp": time.time() }) # 记录审计日志 if self.auth_config["enable_audit_logging"]: self._log_auth_event("auth_failed", client_id, client_ip) return auth_result except Exception as e: print(f"✗ 客户端认证失败: {e}") self.auth_stats["auth_errors"] += 1 return False def _is_ip_blocked(self, client_ip: str) -> bool: """ 检查IP是否被阻止 Args: client_ip: 客户端IP Returns: IP是否被阻止 """ try: if not self.auth_config["enable_ip_filtering"]: return False if client_ip in self.blocked_ips: block_data = self.blocked_ips[client_ip] if time.time() - block_data["block_time"] < block_data["duration"]: return True else: # 阻止时间已过期,移除 del self.blocked_ips[client_ip] return False except Exception as e: print(f"✗ IP阻止检查失败: {e}") self.auth_stats["auth_errors"] += 1 return False def _is_login_blocked(self, client_ip: str) -> bool: """ 检查登录是否被阻止 Args: client_ip: 客户端IP Returns: 登录是否被阻止 """ try: if client_ip in self.login_attempts: attempts = self.login_attempts[client_ip] if (attempts["count"] >= self.auth_config["max_login_attempts"] and time.time() - attempts["last_attempt"] < self.auth_config["login_lockout_duration"]): return True return False except Exception as e: print(f"✗ 登录阻止检查失败: {e}") self.auth_stats["auth_errors"] += 1 return False def _record_failed_login(self, client_ip: str): """ 记录失败的登录尝试 Args: client_ip: 客户端IP """ try: current_time = time.time() if client_ip not in self.login_attempts: self.login_attempts[client_ip] = { "count": 1, "last_attempt": current_time } else: self.login_attempts[client_ip]["count"] += 1 self.login_attempts[client_ip]["last_attempt"] = current_time # 如果超过最大尝试次数,阻止IP if (self.login_attempts[client_ip]["count"] >= self.auth_config["max_login_attempts"]): self._block_ip(client_ip, self.auth_config["login_lockout_duration"]) except Exception as e: print(f"✗ 失败登录记录失败: {e}") self.auth_stats["auth_errors"] += 1 def _perform_authentication(self, client_id: str, auth_data: Dict[str, Any]) -> bool: """ 执行认证 Args: client_id: 客户端ID auth_data: 认证数据 Returns: 是否认证成功 """ try: # 检查认证类型 auth_type = auth_data.get("auth_type", "token") if auth_type == "token": return self._authenticate_with_token(client_id, auth_data) elif auth_type == "password": return self._authenticate_with_password(client_id, auth_data) elif auth_type == "session": return self._authenticate_with_session(client_id, auth_data) else: # 默认认证方式 return self._authenticate_with_token(client_id, auth_data) except Exception as e: print(f"✗ 认证执行失败: {e}") self.auth_stats["auth_errors"] += 1 return False def _authenticate_with_token(self, client_id: str, auth_data: Dict[str, Any]) -> bool: """ 使用令牌认证 Args: client_id: 客户端ID auth_data: 认证数据 Returns: 是否认证成功 """ try: token = auth_data.get("token") if not token: return False # 验证令牌 if token in self.tokens: token_data = self.tokens[token] if time.time() - token_data["created_time"] < self.auth_config["token_lifetime"]: # 令牌有效,创建会话 self._create_session(client_id, auth_data) return True else: # 令牌过期,移除 del self.tokens[token] return False except Exception as e: print(f"✗ 令牌认证失败: {e}") self.auth_stats["auth_errors"] += 1 return False def _authenticate_with_password(self, client_id: str, auth_data: Dict[str, Any]) -> bool: """ 使用密码认证 Args: client_id: 客户端ID auth_data: 认证数据 Returns: 是否认证成功 """ try: username = auth_data.get("username") password = auth_data.get("password") if not username or not password: return False # 验证密码(简化实现) # 在实际应用中,这里应该连接到用户数据库验证用户名和密码 if username == "test_user" and password == "test_password": # 创建会话 self._create_session(client_id, auth_data) return True else: return False except Exception as e: print(f"✗ 密码认证失败: {e}") self.auth_stats["auth_errors"] += 1 return False def _authenticate_with_session(self, client_id: str, auth_data: Dict[str, Any]) -> bool: """ 使用会话认证 Args: client_id: 客户端ID auth_data: 认证数据 Returns: 是否认证成功 """ try: session_id = auth_data.get("session_id") if not session_id: return False # 检查会话是否存在且有效 if session_id in self.sessions: session_data = self.sessions[session_id] if time.time() - session_data["login_time"] < self.auth_config["session_timeout"]: # 更新会话最后活动时间 session_data["last_activity"] = time.time() return True return False except Exception as e: print(f"✗ 会话认证失败: {e}") self.auth_stats["auth_errors"] += 1 return False def _create_session(self, client_id: str, auth_data: Dict[str, Any]): """ 创建会话 Args: client_id: 客户端ID auth_data: 认证数据 """ try: session_id = self._generate_session_id() session_data = { "client_id": client_id, "login_time": time.time(), "last_activity": time.time(), "user_id": auth_data.get("user_id", ""), "username": auth_data.get("username", ""), "permissions": auth_data.get("permissions", []) } self.sessions[session_id] = session_data self.auth_state["active_sessions"] += 1 self.auth_stats["sessions_created"] += 1 # 触发会话创建回调 self._trigger_auth_callback("session_created", { "session_id": session_id, "client_id": client_id, "auth_data": auth_data, "timestamp": time.time() }) except Exception as e: print(f"✗ 会话创建失败: {e}") self.auth_stats["auth_errors"] += 1 def _generate_session_id(self) -> str: """ 生成会话ID Returns: 生成的会话ID """ try: return secrets.token_urlsafe(32) except Exception as e: print(f"✗ 会话ID生成失败: {e}") self.auth_stats["auth_errors"] += 1 return f"session_{int(time.time() * 1000000)}" def generate_token(self, user_id: str, permissions: List[str] = None) -> str: """ 生成令牌 Args: user_id: 用户ID permissions: 权限列表 Returns: 生成的令牌 """ try: token = secrets.token_urlsafe(64) self.tokens[token] = { "user_id": user_id, "permissions": permissions or [], "created_time": time.time() } self.auth_stats["tokens_generated"] += 1 return token except Exception as e: print(f"✗ 令牌生成失败: {e}") self.auth_stats["auth_errors"] += 1 return "" def validate_token(self, token: str) -> bool: """ 验证令牌 Args: token: 令牌 Returns: 令牌是否有效 """ try: if not token: return False if token in self.tokens: token_data = self.tokens[token] if time.time() - token_data["created_time"] < self.auth_config["token_lifetime"]: return True else: # 令牌过期,移除 del self.tokens[token] return False except Exception as e: print(f"✗ 令牌验证失败: {e}") self.auth_stats["auth_errors"] += 1 return False def hash_password(self, password: str, salt: str = None) -> Dict[str, str]: """ 哈希密码 Args: password: 密码 salt: 盐值(可选) Returns: 包含哈希值和盐值的字典 """ try: if salt is None: salt = secrets.token_hex(16) # 使用PBKDF2哈希密码 password_hash = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt.encode('utf-8'), 100000) return { "hash": password_hash.hex(), "salt": salt } except Exception as e: print(f"✗ 密码哈希失败: {e}") self.auth_stats["auth_errors"] += 1 return {} def verify_password(self, password: str, password_hash: str, salt: str) -> bool: """ 验证密码 Args: password: 密码 password_hash: 密码哈希值 salt: 盐值 Returns: 密码是否正确 """ try: # 重新哈希密码 new_hash = hashlib.pbkdf2_hmac('sha256', password.encode('utf-8'), salt.encode('utf-8'), 100000) return hmac.compare_digest(new_hash.hex(), password_hash) except Exception as e: print(f"✗ 密码验证失败: {e}") self.auth_stats["auth_errors"] += 1 return False def _block_ip(self, client_ip: str, duration: float): """ 阻止IP地址 Args: client_ip: 客户端IP duration: 阻止持续时间(秒) """ try: self.blocked_ips[client_ip] = { "block_time": time.time(), "duration": duration } # 触发用户禁止回调 self._trigger_auth_callback("user_banned", { "ip_address": client_ip, "duration": duration, "timestamp": time.time() }) # 记录审计日志 if self.auth_config["enable_audit_logging"]: self._log_auth_event("ip_blocked", None, client_ip) print(f"✓ IP地址已被阻止: {client_ip} (持续 {duration} 秒)") except Exception as e: print(f"✗ IP阻止失败: {e}") self.auth_stats["auth_errors"] += 1 def unblock_ip(self, client_ip: str) -> bool: """ 解除IP阻止 Args: client_ip: 客户端IP Returns: 是否解除成功 """ try: if client_ip in self.blocked_ips: del self.blocked_ips[client_ip] print(f"✓ IP地址阻止已解除: {client_ip}") return True else: print(f"✗ IP地址未被阻止: {client_ip}") return False except Exception as e: print(f"✗ IP阻止解除失败: {e}") self.auth_stats["auth_errors"] += 1 return False def _log_auth_event(self, event_type: str, client_id: str = None, client_ip: str = None): """ 记录认证事件 Args: event_type: 事件类型 client_id: 客户端ID(可选) client_ip: 客户端IP(可选) """ try: if not self.auth_config["enable_audit_logging"]: return event = { "event_type": event_type, "client_id": client_id, "client_ip": client_ip, "timestamp": time.time() } # 在实际实现中,这里会将事件记录到日志文件或数据库 print(f"[认证日志] {event_type} - 客户端: {client_id}, IP: {client_ip}") except Exception as e: print(f"✗ 认证事件记录失败: {e}") self.auth_stats["auth_errors"] += 1 def get_active_sessions(self) -> Dict[str, Any]: """ 获取活跃会话 Returns: 活跃会话字典 """ try: return self.sessions.copy() except Exception as e: print(f"✗ 获取活跃会话失败: {e}") self.auth_stats["auth_errors"] += 1 return {} def get_blocked_ips(self) -> Dict[str, Any]: """ 获取被阻止的IP地址 Returns: 被阻止的IP地址字典 """ try: return self.blocked_ips.copy() except Exception as e: print(f"✗ 获取被阻止的IP地址失败: {e}") self.auth_stats["auth_errors"] += 1 return {} def get_auth_stats(self) -> Dict[str, Any]: """ 获取认证统计信息 Returns: 认证统计字典 """ return { "state": self.auth_state.copy(), "stats": self.auth_stats.copy(), "config": self.auth_config.copy() } def reset_stats(self): """重置认证统计信息""" try: self.auth_stats = { "tokens_generated": 0, "sessions_created": 0, "sessions_expired": 0, "users_banned": 0, "auth_errors": 0 } print("✓ 认证统计信息已重置") except Exception as e: print(f"✗ 认证统计信息重置失败: {e}") def set_auth_config(self, config: Dict[str, Any]) -> bool: """ 设置认证配置 Args: config: 认证配置字典 Returns: 是否设置成功 """ try: self.auth_config.update(config) print(f"✓ 认证配置已更新: {self.auth_config}") return True except Exception as e: print(f"✗ 认证配置设置失败: {e}") return False def get_auth_config(self) -> Dict[str, Any]: """ 获取认证配置 Returns: 认证配置字典 """ return self.auth_config.copy() def _trigger_auth_callback(self, callback_type: str, data: Dict[str, Any]): """ 触发认证回调 Args: callback_type: 回调类型 data: 回调数据 """ try: if callback_type in self.auth_callbacks: for callback in self.auth_callbacks[callback_type]: try: callback(data) except Exception as e: print(f"✗ 认证回调执行失败: {callback_type} - {e}") except Exception as e: print(f"✗ 认证回调触发失败: {e}") def register_auth_callback(self, callback_type: str, callback: callable): """ 注册认证回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.auth_callbacks: self.auth_callbacks[callback_type].append(callback) print(f"✓ 认证回调已注册: {callback_type}") else: print(f"✗ 无效的回调类型: {callback_type}") except Exception as e: print(f"✗ 认证回调注册失败: {e}") def unregister_auth_callback(self, callback_type: str, callback: callable): """ 注销认证回调 Args: callback_type: 回调类型 callback: 回调函数 """ try: if callback_type in self.auth_callbacks: if callback in self.auth_callbacks[callback_type]: self.auth_callbacks[callback_type].remove(callback) print(f"✓ 认证回调已注销: {callback_type}") else: print(f"✗ 无效的回调类型: {callback_type}") except Exception as e: print(f"✗ 认证回调注销失败: {e}")