Skip to content

权限管理与安全常见问题

权限控制相关

Q: 如何设置用户访问权限?

A: Sira AI 提供多层级的权限控制系统:

1. 角色权限设置:

json
{
  "roles": {
    "admin": {
      "name": "系统管理员",
      "permissions": [
        "manage_assistants",
        "manage_users", 
        "manage_models",
        "view_analytics",
        "system_settings"
      ]
    },
    "manager": {
      "name": "部门经理",
      "permissions": [
        "manage_department_assistants",
        "view_department_analytics",
        "manage_department_users"
      ]
    },
    "user": {
      "name": "普通用户",
      "permissions": [
        "use_assistants",
        "view_own_conversations"
      ]
    }
  }
}

2. 部门级权限控制:

  • 进入「权限管理」→「部门权限」
  • 选择部门并设置:
    • 可访问的应用列表
    • 可使用的 AI 模型
    • 每日使用配额限制
    • 功能权限开关

3. 用户级精细权限:

python
# 用户权限配置示例
user_permissions = {
    "user_id": "zhang.san",
    "department": "sales",
    "role": "manager",
    "custom_permissions": {
        "ai_models": ["gpt-3.5-turbo", "qwen-turbo"],
        "daily_quota": 1000,  # tokens
        "features": {
            "image_analysis": True,
            "file_upload": True,
            "export_conversations": False
        },
        "time_restrictions": {
            "allowed_hours": "09:00-18:00",
            "weekdays_only": True
        }
    }
}

4. 动态权限验证:

python
def check_permission(user_id: str, action: str, resource: str = None) -> bool:
    """权限检查函数"""
    user = get_user_info(user_id)
    
    # 检查基础角色权限
    if not has_role_permission(user.role, action):
        return False
    
    # 检查时间限制
    if not check_time_restrictions(user):
        return False
    
    # 检查配额限制
    if not check_quota_limits(user, action):
        return False
    
    # 检查资源级权限
    if resource and not check_resource_permission(user, resource):
        return False
    
    return True

Q: 如何实现单点登录(SSO)集成?

A: Sira AI 支持多种 SSO 方案:

1. 企业微信SSO集成:

javascript
// 前端 SDK 配置
const weworkConfig = {
  corpId: 'your_corp_id',
  agentId: 'your_agent_id',
  redirectUri: 'https://your-domain.com/auth/callback',
  scope: 'snsapi_base',
  state: 'random_state_string'
};

// 发起授权
function initiateWeworkAuth() {
  const authUrl = `https://open.weixin.qq.com/connect/oauth2/authorize?` +
    `appid=${weworkConfig.corpId}&` +
    `redirect_uri=${encodeURIComponent(weworkConfig.redirectUri)}&` +
    `response_type=code&` +
    `scope=${weworkConfig.scope}&` +
    `agentid=${weworkConfig.agentId}&` +
    `state=${weworkConfig.state}`;
  
  window.location.href = authUrl;
}

2. LDAP/AD 集成:

python
import ldap3

class LDAPAuthenticator:
    def __init__(self, server_url, base_dn, bind_user, bind_password):
        self.server = ldap3.Server(server_url)
        self.base_dn = base_dn
        self.connection = ldap3.Connection(
            self.server, 
            bind_user, 
            bind_password
        )
    
    def authenticate_user(self, username: str, password: str) -> dict:
        """LDAP用户认证"""
        try:
            # 搜索用户
            user_dn = f"cn={username},{self.base_dn}"
            
            # 尝试绑定用户
            user_conn = ldap3.Connection(self.server, user_dn, password)
            
            if user_conn.bind():
                # 获取用户信息
                user_info = self._get_user_info(username)
                return {
                    "success": True,
                    "user_info": user_info
                }
            else:
                return {"success": False, "error": "认证失败"}
                
        except Exception as e:
            return {"success": False, "error": str(e)}
    
    def _get_user_info(self, username: str) -> dict:
        """获取用户详细信息"""
        search_filter = f"(cn={username})"
        
        self.connection.search(
            self.base_dn,
            search_filter,
            attributes=['cn', 'mail', 'department', 'title']
        )
        
        if self.connection.entries:
            entry = self.connection.entries[0]
            return {
                "username": str(entry.cn),
                "email": str(entry.mail) if entry.mail else None,
                "department": str(entry.department) if entry.department else None,
                "title": str(entry.title) if entry.title else None
            }
        
        return {}

3. OIDC/OAuth2 集成:

python
from authlib.integrations.flask_client import OAuth

class OIDCProvider:
    def __init__(self, app, config):
        self.oauth = OAuth(app)
        
        # 注册OIDC提供商
        self.client = self.oauth.register(
            name='enterprise_sso',
            client_id=config['CLIENT_ID'],
            client_secret=config['CLIENT_SECRET'],
            server_metadata_url=config['DISCOVERY_URL'],
            client_kwargs={
                'scope': 'openid email profile'
            }
        )
    
    def get_authorization_url(self, redirect_uri: str) -> str:
        """获取授权URL"""
        return self.client.authorize_redirect(redirect_uri).location
    
    def handle_callback(self, code: str) -> dict:
        """处理回调并获取用户信息"""
        try:
            token = self.client.authorize_access_token()
            user_info = self.client.parse_id_token(token)
            
            return {
                "success": True,
                "user_info": {
                    "sub": user_info.get('sub'),
                    "email": user_info.get('email'),
                    "name": user_info.get('name'),
                    "department": user_info.get('department')
                },
                "access_token": token['access_token']
            }
        except Exception as e:
            return {"success": False, "error": str(e)}

4. 自动用户映射:

python
def map_sso_user_to_local(sso_user_info: dict) -> dict:
    """将SSO用户信息映射到本地用户"""
    # 检查用户是否已存在
    local_user = User.query.filter_by(email=sso_user_info['email']).first()
    
    if not local_user:
        # 创建新用户
        local_user = User(
            username=sso_user_info['email'],
            email=sso_user_info['email'],
            display_name=sso_user_info.get('name'),
            department=sso_user_info.get('department'),
            is_active=True,
            auth_source='sso'
        )
        
        # 根据部门分配默认角色
        local_user.role = determine_default_role(sso_user_info.get('department'))
        
        db.session.add(local_user)
        db.session.commit()
    
    return {
        "user_id": local_user.id,
        "username": local_user.username,
        "role": local_user.role,
        "permissions": get_user_permissions(local_user.id)
    }

Q: 如何设置API访问权限?

A: API权限管控方案:

1. API密钥管理:

python
import secrets
import hashlib
from datetime import datetime, timedelta

class APIKeyManager:
    def __init__(self):
        self.keys = {}  # 实际应存储在数据库中
    
    def generate_api_key(self, user_id: str, permissions: list, expires_days: int = 365) -> dict:
        """生成API密钥"""
        # 生成密钥
        raw_key = secrets.token_urlsafe(32)
        key_hash = hashlib.sha256(raw_key.encode()).hexdigest()
        
        # 存储密钥信息
        api_key_info = {
            "key_hash": key_hash,
            "user_id": user_id,
            "permissions": permissions,
            "created_at": datetime.now(),
            "expires_at": datetime.now() + timedelta(days=expires_days),
            "is_active": True,
            "last_used": None,
            "usage_count": 0
        }
        
        self.keys[key_hash] = api_key_info
        
        return {
            "api_key": f"tcf_{raw_key}",  # 添加前缀便于识别
            "key_id": key_hash[:8],  # 用于显示的短ID
            "expires_at": api_key_info["expires_at"],
            "permissions": permissions
        }
    
    def validate_api_key(self, api_key: str) -> dict:
        """验证API密钥"""
        if not api_key.startswith("tcf_"):
            return {"valid": False, "error": "无效的密钥格式"}
        
        raw_key = api_key[4:]  # 移除前缀
        key_hash = hashlib.sha256(raw_key.encode()).hexdigest()
        
        key_info = self.keys.get(key_hash)
        if not key_info:
            return {"valid": False, "error": "密钥不存在"}
        
        if not key_info["is_active"]:
            return {"valid": False, "error": "密钥已禁用"}
        
        if datetime.now() > key_info["expires_at"]:
            return {"valid": False, "error": "密钥已过期"}
        
        # 更新使用信息
        key_info["last_used"] = datetime.now()
        key_info["usage_count"] += 1
        
        return {
            "valid": True,
            "user_id": key_info["user_id"],
            "permissions": key_info["permissions"]
        }

2. API权限装饰器:

python
from functools import wraps
from flask import request, jsonify

def require_api_permission(permission: str):
    """API权限检查装饰器"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            # 获取API密钥
            api_key = request.headers.get('Authorization', '')
            if api_key.startswith('Bearer '):
                api_key = api_key[7:]
            
            # 验证密钥
            key_validation = api_key_manager.validate_api_key(api_key)
            
            if not key_validation["valid"]:
                return jsonify({
                    "error": "API认证失败",
                    "message": key_validation["error"]
                }), 401
            
            # 检查权限
            if permission not in key_validation["permissions"]:
                return jsonify({
                    "error": "权限不足",
                    "required_permission": permission
                }), 403
            
            # 添加用户信息到请求上下文
            request.current_user_id = key_validation["user_id"]
            request.current_permissions = key_validation["permissions"]
            
            return func(*args, **kwargs)
        return wrapper
    return decorator

# 使用示例
@app.route('/api/assistants', methods=['GET'])
@require_api_permission('read_assistants')
def list_assistants():
    user_id = request.current_user_id
    # 获取用户可访问的助手列表
    assistants = get_user_assistants(user_id)
    return jsonify(assistants)

@app.route('/api/assistants', methods=['POST'])
@require_api_permission('create_assistants')
def create_assistant():
    # 创建助手逻辑
    pass

3. API限流控制:

python
from collections import defaultdict
import time

class APIRateLimiter:
    def __init__(self):
        self.requests = defaultdict(list)
        self.limits = {
            "basic": {"requests": 100, "window": 3600},  # 100请求/小时
            "premium": {"requests": 1000, "window": 3600},  # 1000请求/小时
            "enterprise": {"requests": 10000, "window": 3600}  # 10000请求/小时
        }
    
    def is_allowed(self, user_id: str, tier: str = "basic") -> bool:
        """检查是否允许请求"""
        current_time = time.time()
        limit_info = self.limits.get(tier, self.limits["basic"])
        
        # 清除过期记录
        window_start = current_time - limit_info["window"]
        self.requests[user_id] = [
            req_time for req_time in self.requests[user_id]
            if req_time > window_start
        ]
        
        # 检查是否超过限制
        if len(self.requests[user_id]) >= limit_info["requests"]:
            return False
        
        # 记录当前请求
        self.requests[user_id].append(current_time)
        return True

# 限流装饰器
def rate_limit(tier: str = "basic"):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            user_id = request.current_user_id
            
            if not rate_limiter.is_allowed(user_id, tier):
                return jsonify({
                    "error": "请求频率过高",
                    "message": f"已超过 {tier} 级别的请求限制"
                }), 429
            
            return func(*args, **kwargs)
        return wrapper
    return decorator

Q: 如何实现数据权限隔离?

A: 数据隔离策略实现:

1. 多租户数据架构:

python
class MultiTenantQuery:
    """多租户查询基类"""
    
    @classmethod
    def get_tenant_filter(cls, user_id: str):
        """获取租户过滤条件"""
        user = get_user_info(user_id)
        
        if user.role == 'admin':
            # 管理员可以看到所有数据
            return {}
        elif user.role == 'department_manager':
            # 部门经理只能看到本部门数据
            return {"department": user.department}
        else:
            # 普通用户只能看到自己的数据
            return {"user_id": user_id}
    
    @classmethod
    def filter_by_tenant(cls, query, user_id: str):
        """应用租户过滤"""
        tenant_filter = cls.get_tenant_filter(user_id)
        
        for field, value in tenant_filter.items():
            query = query.filter(getattr(cls, field) == value)
        
        return query

# 使用示例
class Assistant(db.Model, MultiTenantQuery):
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(100))
    user_id = db.Column(db.String(50))
    department = db.Column(db.String(50))
    
    @classmethod
    def get_user_assistants(cls, user_id: str):
        """获取用户可访问的助手"""
        query = cls.query
        query = cls.filter_by_tenant(query, user_id)
        return query.all()

2. 行级安全策略:

sql
-- 数据库行级安全示例(PostgreSQL)
CREATE POLICY assistant_access_policy 
ON assistants
FOR ALL
TO application_role
USING (
  -- 管理员可以访问所有数据
  current_setting('app.user_role') = 'admin'
  OR
  -- 部门经理可以访问本部门数据
  (current_setting('app.user_role') = 'manager' 
   AND department = current_setting('app.user_department'))
  OR
  -- 用户只能访问自己的数据
  user_id = current_setting('app.user_id')
);

-- 启用行级安全
ALTER TABLE assistants ENABLE ROW LEVEL SECURITY;

3. 字段级权限控制:

python
class FieldLevelSecurity:
    """字段级安全控制"""
    
    # 字段访问权限配置
    FIELD_PERMISSIONS = {
        "assistant": {
            "basic_fields": ["id", "name", "description"],
            "sensitive_fields": ["api_key", "config"],
            "admin_fields": ["created_by", "system_config"]
        },
        "conversation": {
            "basic_fields": ["id", "content", "timestamp"],
            "private_fields": ["user_info", "ip_address"],
            "analytics_fields": ["metrics", "performance_data"]
        }
    }
    
    def filter_fields(self, data: dict, entity_type: str, user_role: str) -> dict:
        """根据用户角色过滤字段"""
        permissions = self.FIELD_PERMISSIONS.get(entity_type, {})
        allowed_fields = permissions.get("basic_fields", [])
        
        if user_role == "admin":
            # 管理员可以看到所有字段
            allowed_fields.extend(permissions.get("sensitive_fields", []))
            allowed_fields.extend(permissions.get("admin_fields", []))
        elif user_role == "manager":
            # 经理可以看到基础字段和分析字段
            allowed_fields.extend(permissions.get("analytics_fields", []))
        
        # 过滤数据
        filtered_data = {
            key: value for key, value in data.items()
            if key in allowed_fields
        }
        
        return filtered_data

4. 数据访问审计:

python
class DataAccessAuditor:
    """数据访问审计"""
    
    def log_data_access(self, user_id: str, action: str, resource: str, 
                       resource_id: str = None, result: str = "success"):
        """记录数据访问日志"""
        audit_log = {
            "timestamp": datetime.now(),
            "user_id": user_id,
            "action": action,  # read, create, update, delete
            "resource": resource,  # assistant, conversation, model
            "resource_id": resource_id,
            "result": result,  # success, denied, error
            "ip_address": get_client_ip(),
            "user_agent": get_user_agent()
        }
        
        # 存储到审计日志表
        db.session.add(AuditLog(**audit_log))
        db.session.commit()
        
        # 异步发送到日志分析系统
        self.send_to_log_system(audit_log)
    
    def check_suspicious_activity(self, user_id: str):
        """检查可疑活动"""
        # 检查短时间内大量访问
        recent_accesses = AuditLog.query.filter(
            AuditLog.user_id == user_id,
            AuditLog.timestamp > datetime.now() - timedelta(minutes=10)
        ).count()
        
        if recent_accesses > 100:  # 10分钟内超过100次访问
            self.trigger_security_alert(user_id, "高频访问")
        
        # 检查异常访问模式
        failed_accesses = AuditLog.query.filter(
            AuditLog.user_id == user_id,
            AuditLog.result == "denied",
            AuditLog.timestamp > datetime.now() - timedelta(hours=1)
        ).count()
        
        if failed_accesses > 10:  # 1小时内超过10次被拒绝
            self.trigger_security_alert(user_id, "频繁权限拒绝")

# 访问控制装饰器
def audit_data_access(resource: str):
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            user_id = getattr(request, 'current_user_id', 'anonymous')
            action = request.method.lower()
            
            try:
                result = func(*args, **kwargs)
                auditor.log_data_access(user_id, action, resource, result="success")
                return result
            except PermissionError:
                auditor.log_data_access(user_id, action, resource, result="denied")
                raise
            except Exception as e:
                auditor.log_data_access(user_id, action, resource, result="error")
                raise
        return wrapper
    return decorator

数据安全相关

Q: 如何确保对话数据的安全性?

A: 对话数据安全保护措施:

1. 数据加密存储:

python
from cryptography.fernet import Fernet
import base64
import hashlib

class ConversationEncryption:
    def __init__(self, master_key: str):
        # 基于主密钥生成加密密钥
        key_hash = hashlib.sha256(master_key.encode()).digest()
        self.cipher = Fernet(base64.urlsafe_b64encode(key_hash))
    
    def encrypt_conversation(self, content: str) -> str:
        """加密对话内容"""
        encrypted_data = self.cipher.encrypt(content.encode())
        return base64.urlsafe_b64encode(encrypted_data).decode()
    
    def decrypt_conversation(self, encrypted_content: str) -> str:
        """解密对话内容"""
        try:
            encrypted_data = base64.urlsafe_b64decode(encrypted_content.encode())
            decrypted_data = self.cipher.decrypt(encrypted_data)
            return decrypted_data.decode()
        except Exception as e:
            logger.error(f"解密失败: {e}")
            return "[加密内容无法解密]"
    
    def rotate_encryption_key(self, new_master_key: str):
        """密钥轮换"""
        new_key_hash = hashlib.sha256(new_master_key.encode()).digest()
        new_cipher = Fernet(base64.urlsafe_b64encode(new_key_hash))
        
        # 重新加密所有对话数据
        conversations = Conversation.query.all()
        
        for conv in conversations:
            # 用旧密钥解密
            decrypted_content = self.decrypt_conversation(conv.content)
            # 用新密钥加密
            conv.content = new_cipher.encrypt(decrypted_content.encode())
        
        db.session.commit()
        self.cipher = new_cipher

2. 敏感信息检测和脱敏:

python
import re
from typing import List, Dict

class SensitiveDataDetector:
    def __init__(self):
        # 敏感信息正则表达式
        self.patterns = {
            "phone": r'1[3-9]\d{9}',  # 手机号
            "email": r'\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b',
            "id_card": r'\d{17}[\dXx]',  # 身份证号
            "bank_card": r'\d{16,19}',  # 银行卡号
            "ip_address": r'\b(?:\d{1,3}\.){3}\d{1,3}\b',
            "credit_card": r'\b(?:\d{4}[-\s]?){3}\d{4}\b'
        }
    
    def detect_sensitive_data(self, text: str) -> List[Dict]:
        """检测敏感数据"""
        detected = []
        
        for data_type, pattern in self.patterns.items():
            matches = re.finditer(pattern, text)
            
            for match in matches:
                detected.append({
                    "type": data_type,
                    "value": match.group(),
                    "start": match.start(),
                    "end": match.end(),
                    "confidence": self._calculate_confidence(data_type, match.group())
                })
        
        return detected
    
    def mask_sensitive_data(self, text: str, mask_char: str = "*") -> str:
        """脱敏处理"""
        masked_text = text
        detected_data = self.detect_sensitive_data(text)
        
        # 按位置倒序处理,避免位置偏移
        for item in sorted(detected_data, key=lambda x: x['start'], reverse=True):
            value = item['value']
            
            if item['type'] == 'phone':
                # 手机号:保留前3位和后4位
                masked_value = value[:3] + mask_char * 4 + value[-4:]
            elif item['type'] == 'email':
                # 邮箱:保留域名,用户名部分脱敏
                local, domain = value.split('@')
                masked_local = local[:2] + mask_char * (len(local) - 2)
                masked_value = f"{masked_local}@{domain}"
            elif item['type'] == 'id_card':
                # 身份证:保留前6位和后4位
                masked_value = value[:6] + mask_char * 8 + value[-4:]
            else:
                # 其他类型:保留前后各2位
                if len(value) > 4:
                    masked_value = value[:2] + mask_char * (len(value) - 4) + value[-2:]
                else:
                    masked_value = mask_char * len(value)
            
            masked_text = masked_text[:item['start']] + masked_value + masked_text[item['end']:]
        
        return masked_text
    
    def _calculate_confidence(self, data_type: str, value: str) -> float:
        """计算检测置信度"""
        if data_type == "phone" and len(value) == 11:
            return 0.95
        elif data_type == "email" and "@" in value and "." in value:
            return 0.90
        elif data_type == "id_card" and len(value) == 18:
            return 0.85
        else:
            return 0.70

3. 数据访问控制:

python
class ConversationAccessControl:
    """对话数据访问控制"""
    
    def __init__(self, encryption_service, detector_service):
        self.encryption = encryption_service
        self.detector = detector_service
    
    def get_conversation(self, conversation_id: str, user_id: str, 
                        include_sensitive: bool = False) -> dict:
        """获取对话数据"""
        # 权限检查
        if not self._check_access_permission(conversation_id, user_id):
            raise PermissionError("无权访问此对话")
        
        # 获取加密对话
        conversation = Conversation.query.get(conversation_id)
        
        # 解密内容
        decrypted_content = self.encryption.decrypt_conversation(conversation.content)
        
        # 根据权限决定是否脱敏
        if not include_sensitive:
            decrypted_content = self.detector.mask_sensitive_data(decrypted_content)
        
        return {
            "id": conversation.id,
            "content": decrypted_content,
            "timestamp": conversation.timestamp,
            "user_id": conversation.user_id
        }
    
    def _check_access_permission(self, conversation_id: str, user_id: str) -> bool:
        """检查访问权限"""
        conversation = Conversation.query.get(conversation_id)
        user = User.query.get(user_id)
        
        # 用户只能访问自己的对话
        if conversation.user_id == user_id:
            return True
        
        # 管理员可以访问所有对话
        if user.role == 'admin':
            return True
        
        # 部门经理可以访问本部门的对话
        if user.role == 'manager':
            conversation_user = User.query.get(conversation.user_id)
            return conversation_user.department == user.department
        
        return False

4. 数据保留和清理策略:

python
from datetime import datetime, timedelta

class DataRetentionManager:
    """数据保留管理"""
    
    def __init__(self):
        # 数据保留策略配置
        self.retention_policies = {
            "conversation": {
                "basic_user": 90,    # 普通用户90天
                "premium_user": 365, # 高级用户1年
                "admin": -1          # 管理员数据永久保留
            },
            "audit_log": {
                "security_events": 2555,  # 安全事件7年
                "access_logs": 365,       # 访问日志1年
                "error_logs": 180         # 错误日志6个月
            }
        }
    
    def cleanup_expired_data(self):
        """清理过期数据"""
        # 清理过期对话
        self._cleanup_expired_conversations()
        
        # 清理过期日志
        self._cleanup_expired_logs()
        
        # 清理临时文件
        self._cleanup_temporary_files()
    
    def _cleanup_expired_conversations(self):
        """清理过期对话"""
        for user_type, retention_days in self.retention_policies["conversation"].items():
            if retention_days == -1:  # 永久保留
                continue
            
            cutoff_date = datetime.now() - timedelta(days=retention_days)
            
            # 查找过期对话
            expired_conversations = Conversation.query.join(User).filter(
                User.user_type == user_type,
                Conversation.created_at < cutoff_date
            ).all()
            
            for conversation in expired_conversations:
                # 记录删除操作
                self._log_data_deletion("conversation", conversation.id)
                
                # 删除对话
                db.session.delete(conversation)
            
            db.session.commit()
            logger.info(f"清理了 {len(expired_conversations)}{user_type} 过期对话")
    
    def _log_data_deletion(self, data_type: str, data_id: str):
        """记录数据删除日志"""
        deletion_log = {
            "timestamp": datetime.now(),
            "data_type": data_type,
            "data_id": data_id,
            "reason": "retention_policy",
            "operator": "system"
        }
        
        # 存储删除记录
        db.session.add(DeletionLog(**deletion_log))

Q: 如何防范数据泄露风险?

A: 数据防泄露综合方案:

1. DLP(数据丢失防护)系统:

python
class DataLeakagePreventionSystem:
    def __init__(self):
        self.risk_patterns = {
            "high_risk": {
                "patterns": [
                    r"(?i)密码.*[::]\s*\w+",  # 密码信息
                    r"(?i)secret.*[::]\s*\w+",  # 机密信息
                    r"(?i)token.*[::]\s*[\w\-_]+",  # API令牌
                ],
                "action": "block"
            },
            "medium_risk": {
                "patterns": [
                    r"\d{15,19}",  # 银行卡号
                    r"\d{17}[\dXx]",  # 身份证号
                    r"(?i)confidential|机密|内部使用"  # 机密标识
                ],
                "action": "alert"
            },
            "low_risk": {
                "patterns": [
                    r"1[3-9]\d{9}",  # 手机号
                    r"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b"  # 邮箱
                ],
                "action": "log"
            }
        }
    
    def scan_content(self, content: str, context: dict = None) -> dict:
        """扫描内容中的敏感信息"""
        scan_result = {
            "risk_level": "low",
            "violations": [],
            "action": "allow",
            "recommendations": []
        }
        
        highest_risk = "low"
        
        for risk_level, config in self.risk_patterns.items():
            for pattern in config["patterns"]:
                matches = re.finditer(pattern, content)
                
                for match in matches:
                    violation = {
                        "risk_level": risk_level,
                        "pattern": pattern,
                        "match": match.group(),
                        "position": (match.start(), match.end()),
                        "context": content[max(0, match.start()-20):match.end()+20]
                    }
                    
                    scan_result["violations"].append(violation)
                    
                    # 更新最高风险等级
                    if self._get_risk_priority(risk_level) > self._get_risk_priority(highest_risk):
                        highest_risk = risk_level
        
        scan_result["risk_level"] = highest_risk
        scan_result["action"] = self.risk_patterns[highest_risk]["action"]
        
        return scan_result
    
    def _get_risk_priority(self, risk_level: str) -> int:
        return {"low": 1, "medium": 2, "high": 3}.get(risk_level, 0)

2. 水印和溯源技术:

python
class DigitalWatermarking:
    """数字水印系统"""
    
    def __init__(self, secret_key: str):
        self.secret_key = secret_key
    
    def add_invisible_watermark(self, text: str, user_id: str, timestamp: str = None) -> str:
        """添加不可见水印"""
        if not timestamp:
            timestamp = datetime.now().isoformat()
        
        # 创建水印信息
        watermark_data = {
            "user_id": user_id,
            "timestamp": timestamp,
            "hash": hashlib.md5(f"{text}{self.secret_key}".encode()).hexdigest()[:8]
        }
        
        # 将水印编码为不可见字符
        watermark_string = self._encode_watermark(watermark_data)
        
        # 在文本中随机位置插入水印
        positions = self._calculate_insertion_positions(text, watermark_string)
        
        watermarked_text = text
        for pos, char in zip(positions, watermark_string):
            watermarked_text = watermarked_text[:pos] + char + watermarked_text[pos:]
        
        return watermarked_text
    
    def extract_watermark(self, text: str) -> dict:
        """提取水印信息"""
        try:
            # 提取隐藏字符
            hidden_chars = self._extract_hidden_chars(text)
            
            # 解码水印
            watermark_data = self._decode_watermark(hidden_chars)
            
            return {
                "found": True,
                "user_id": watermark_data.get("user_id"),
                "timestamp": watermark_data.get("timestamp"),
                "hash": watermark_data.get("hash")
            }
        except Exception as e:
            return {"found": False, "error": str(e)}
    
    def _encode_watermark(self, data: dict) -> str:
        """编码水印为不可见字符"""
        # 使用零宽字符编码
        zero_width_chars = ['\u200B', '\u200C', '\u200D', '\u2060']
        
        json_data = json.dumps(data)
        encoded = ""
        
        for char in json_data:
            # 将字符转换为二进制
            binary = format(ord(char), '08b')
            
            # 用零宽字符表示二进制
            for bit in binary:
                encoded += zero_width_chars[int(bit)] if bit == '1' else zero_width_chars[0]
        
        return encoded

3. 异常行为检测:

python
class AnomalyDetectionSystem:
    """异常行为检测"""
    
    def __init__(self):
        self.user_baselines = {}  # 用户基线行为
        self.alert_thresholds = {
            "bulk_download": 100,  # 批量下载阈值
            "off_hours_access": (22, 6),  # 非工作时间访问
            "rapid_requests": 50,  # 快速请求阈值
            "unusual_data_access": 0.8  # 异常数据访问阈值
        }
    
    def analyze_user_behavior(self, user_id: str, current_activity: dict) -> dict:
        """分析用户行为异常"""
        # 获取用户历史基线
        baseline = self._get_user_baseline(user_id)
        
        anomalies = []
        
        # 检测批量操作
        if current_activity.get("download_count", 0) > self.alert_thresholds["bulk_download"]:
            anomalies.append({
                "type": "bulk_download",
                "severity": "high",
                "description": f"用户在短时间内下载了 {current_activity['download_count']} 个文件"
            })
        
        # 检测非工作时间访问
        current_hour = datetime.now().hour
        if (current_hour >= self.alert_thresholds["off_hours_access"][0] or 
            current_hour <= self.alert_thresholds["off_hours_access"][1]):
            if not baseline.get("regular_off_hours_user", False):
                anomalies.append({
                    "type": "off_hours_access",
                    "severity": "medium", 
                    "description": f"用户在非工作时间 ({current_hour}:00) 访问系统"
                })
        
        # 检测数据访问模式异常
        access_pattern_score = self._calculate_access_pattern_similarity(
            current_activity.get("accessed_resources", []),
            baseline.get("typical_resources", [])
        )
        
        if access_pattern_score < self.alert_thresholds["unusual_data_access"]:
            anomalies.append({
                "type": "unusual_data_access",
                "severity": "medium",
                "description": f"用户访问了异常的数据资源 (相似度: {access_pattern_score:.2f})"
            })
        
        return {
            "user_id": user_id,
            "anomaly_score": len(anomalies) / 3.0,  # 归一化分数
            "anomalies": anomalies,
            "recommendation": self._generate_recommendations(anomalies)
        }
    
    def _generate_recommendations(self, anomalies: List[dict]) -> List[str]:
        """生成安全建议"""
        recommendations = []
        
        high_risk_count = sum(1 for a in anomalies if a["severity"] == "high")
        medium_risk_count = sum(1 for a in anomalies if a["severity"] == "medium")
        
        if high_risk_count > 0:
            recommendations.append("立即暂停用户访问权限并通知安全团队")
        elif medium_risk_count > 2:
            recommendations.append("增强监控该用户的后续活动")
        elif medium_risk_count > 0:
            recommendations.append("向用户发送安全提醒")
        
        return recommendations

Q: 如何实现合规性审计?

A: 合规性审计体系:

1. 审计日志标准化:

python
from enum import Enum
import json

class AuditEventType(Enum):
    LOGIN = "login"
    LOGOUT = "logout"
    DATA_ACCESS = "data_access"
    DATA_MODIFY = "data_modify"
    DATA_EXPORT = "data_export"
    PERMISSION_CHANGE = "permission_change"
    CONFIG_CHANGE = "config_change"
    SECURITY_EVENT = "security_event"

class ComplianceAuditor:
    """合规性审计器"""
    
    def __init__(self, compliance_standards=None):
        # 合规标准配置
        self.standards = compliance_standards or {
            "GDPR": {
                "data_retention": 2555,  # GDPR要求7年
                "consent_tracking": True,
                "right_to_be_forgotten": True
            },
            "SOX": {
                "financial_data_access": "strict",
                "change_approval": "required",
                "audit_trail": "complete"
            },
            "ISO27001": {
                "access_reviews": "quarterly",
                "security_events": "immediate",
                "risk_assessments": "annual"
            }
        }
    
    def log_audit_event(self, event_type: AuditEventType, user_id: str, 
                       details: dict, risk_level: str = "low"):
        """记录审计事件"""
        audit_record = {
            "timestamp": datetime.now().isoformat(),
            "event_id": self._generate_event_id(),
            "event_type": event_type.value,
            "user_id": user_id,
            "session_id": self._get_session_id(),
            "ip_address": self._get_client_ip(),
            "user_agent": self._get_user_agent(),
            "risk_level": risk_level,
            "details": details,
            "compliance_flags": self._check_compliance_requirements(event_type, details)
        }
        
        # 存储审计记录
        self._store_audit_record(audit_record)
        
        # 实时合规性检查
        self._check_real_time_compliance(audit_record)
        
        return audit_record["event_id"]
    
    def generate_compliance_report(self, standard: str, period: str = "monthly") -> dict:
        """生成合规性报告"""
        if standard not in self.standards:
            raise ValueError(f"不支持的合规标准: {standard}")
        
        report = {
            "standard": standard,
            "period": period,
            "generated_at": datetime.now().isoformat(),
            "compliance_status": "compliant",
            "findings": [],
            "recommendations": [],
            "metrics": {}
        }
        
        # 根据不同标准生成报告
        if standard == "GDPR":
            report.update(self._generate_gdpr_report(period))
        elif standard == "SOX":
            report.update(self._generate_sox_report(period))
        elif standard == "ISO27001":
            report.update(self._generate_iso27001_report(period))
        
        return report
    
    def _generate_gdpr_report(self, period: str) -> dict:
        """生成GDPR合规报告"""
        gdpr_metrics = {
            "data_subject_requests": self._count_data_subject_requests(period),
            "consent_changes": self._count_consent_changes(period),
            "data_breaches": self._count_security_incidents(period),
            "data_retention_violations": self._check_retention_violations(period)
        }
        
        findings = []
        recommendations = []
        
        # 检查数据主体权利请求处理时间
        overdue_requests = self._get_overdue_data_requests()
        if overdue_requests:
            findings.append({
                "severity": "high",
                "description": f"{len(overdue_requests)} 个数据主体请求超过30天处理期限",
                "affected_items": overdue_requests
            })
            recommendations.append("建立自动化的数据主体请求处理流程")
        
        return {
            "metrics": gdpr_metrics,
            "findings": findings,
            "recommendations": recommendations
        }
    
    def _check_compliance_requirements(self, event_type: AuditEventType, details: dict) -> List[str]:
        """检查合规性要求"""
        flags = []
        
        # GDPR相关检查
        if event_type == AuditEventType.DATA_ACCESS and "personal_data" in details:
            flags.append("GDPR_PERSONAL_DATA_ACCESS")
        
        if event_type == AuditEventType.DATA_EXPORT:
            flags.append("GDPR_DATA_TRANSFER")
        
        # SOX相关检查
        if "financial" in details.get("data_category", ""):
            flags.append("SOX_FINANCIAL_DATA")
        
        # ISO27001相关检查
        if event_type == AuditEventType.SECURITY_EVENT:
            flags.append("ISO27001_SECURITY_INCIDENT")
        
        return flags

2. 自动化合规检查:

python
class AutomatedComplianceChecker:
    """自动化合规检查"""
    
    def __init__(self):
        self.compliance_rules = {
            "access_review": {
                "frequency": "quarterly",
                "scope": "all_users",
                "requirements": ["manager_approval", "documentation"]
            },
            "password_policy": {
                "min_length": 8,
                "complexity": True,
                "expiry_days": 90,
                "history_count": 5
            },
            "data_classification": {
                "required_fields": ["classification_level", "data_owner"],
                "retention_policies": True
            }
        }
    
    def run_compliance_checks(self) -> dict:
        """运行合规性检查"""
        check_results = {
            "overall_status": "compliant",
            "checks_performed": 0,
            "violations_found": 0,
            "details": []
        }
        
        # 访问权限审查
        access_review_result = self._check_access_reviews()
        check_results["details"].append(access_review_result)
        
        # 密码策略检查
        password_policy_result = self._check_password_policy()
        check_results["details"].append(password_policy_result)
        
        # 数据分类检查
        data_classification_result = self._check_data_classification()
        check_results["details"].append(data_classification_result)
        
        # 汇总结果
        total_violations = sum(
            len(result.get("violations", [])) 
            for result in check_results["details"]
        )
        
        check_results["checks_performed"] = len(check_results["details"])
        check_results["violations_found"] = total_violations
        check_results["overall_status"] = "non_compliant" if total_violations > 0 else "compliant"
        
        return check_results
    
    def _check_access_reviews(self) -> dict:
        """检查访问权限审查"""
        result = {
            "check_name": "access_review",
            "status": "compliant",
            "violations": [],
            "recommendations": []
        }
        
        # 查找需要审查的用户
        users_needing_review = User.query.filter(
            User.last_access_review < datetime.now() - timedelta(days=90)
        ).all()
        
        if users_needing_review:
            result["status"] = "non_compliant"
            result["violations"] = [
                {
                    "user_id": user.id,
                    "last_review": user.last_access_review.isoformat() if user.last_access_review else None,
                    "days_overdue": (datetime.now() - user.last_access_review).days if user.last_access_review else "never"
                }
                for user in users_needing_review
            ]
            result["recommendations"].append("执行季度访问权限审查")
        
        return result

3. 合规报告生成:

python
class ComplianceReportGenerator:
    """合规报告生成器"""
    
    def generate_executive_summary(self, audit_data: dict) -> str:
        """生成执行摘要"""
        template = """
        # 合规性审计执行摘要
        
        ## 总体状况
        - 审计期间:{period}
        - 合规状态:{status}
        - 发现问题:{total_findings}
        - 高风险问题:{high_risk_findings}
        
        ## 关键发现
        {key_findings}
        
        ## 改进建议
        {recommendations}
        
        ## 下一步行动
        {action_items}
        """
        
        return template.format(
            period=audit_data.get("period", "未指定"),
            status=audit_data.get("compliance_status", "未知"),
            total_findings=len(audit_data.get("findings", [])),
            high_risk_findings=len([
                f for f in audit_data.get("findings", [])
                if f.get("severity") == "high"
            ]),
            key_findings=self._format_findings(audit_data.get("findings", [])),
            recommendations=self._format_recommendations(audit_data.get("recommendations", [])),
            action_items=self._generate_action_items(audit_data)
        )

相关链接


安全咨询与支持:

我们的安全专家团队为您提供专业服务:

  • 🔒 安全咨询:security@tcfusion.ai
  • 📋 合规评估:compliance@tcfusion.ai
  • 🚨 安全事件:incident@tcfusion.ai(24/7紧急响应)
  • 📚 安全培训:training@tcfusion.ai

Apache-2.0 Licensed