📖 数据密集型设计

GDPR合规与数据本地化

深入探讨GDPR合规要求与数据本地化策略

一、GDPR概述

GDPR(General Data Protection Regulation)是欧盟通用数据保护条例,于2018年5月25日生效。GDPR旨在保护欧盟公民的数据隐私,对处理欧盟公民数据的所有组织提出了严格的要求。

二、GDPR核心原则

2.1 GDPR七大原则

原则 描述 技术实现
合法性、正当性、透明性 数据处理必须合法、正当、透明 隐私政策、同意机制
目的限制 数据只能用于指定目的 数据分类、访问控制
数据最小化 只收集必要的数据 字段级控制、数据清理
准确性 数据必须准确 数据校验、更正机制
存储限制 数据只保留必要时间 TTL、自动清理
完整性和保密性 数据必须安全 加密、访问控制
问责制 组织必须证明合规 审计日志、合规文档

2.2 GDPR数据主体权利

graph TD A[数据主体权利] --> B[访问权] A --> C[更正权] A --> D[删除权] A --> E[数据可携权] A --> F[限制处理权] A --> G[反对权] B --> B1[访问自己的数据] C --> C1[更正错误数据] D --> D1[删除数据] E --> E1[导出数据] F --> F1[限制数据处理] G --> G1[反对数据处理]

三、GDPR合规实现

3.1 数据映射

识别系统中处理的个人数据:

public class DataMappingService
{
    public List<DataMap> MapPersonalData()
    {
        return new List<DataMap>
        {
            new DataMap { Table = "users", Fields = new[] { "email", "phone", "address" }, Purpose = "用户注册" },
            new DataMap { Table = "orders", Fields = new[] { "user_id", "shipping_address" }, Purpose = "订单处理" },
            new DataMap { Table = "logs", Fields = new[] { "user_id", "ip_address" }, Purpose = "安全审计" }
        };
    }
}

public class DataMap
{
    public string Table { get; set; }
    public string[] Fields { get; set; }
    public string Purpose { get; set; }
}

3.2 同意管理

管理用户对数据处理的同意:

-- 同意记录表
CREATE TABLE consent_logs (
    id INT PRIMARY KEY AUTO_INCREMENT,
    user_id INT,
    consent_type VARCHAR(50),
    consent_status BOOLEAN,
    consent_date DATETIME,
    revoked_date DATETIME,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

-- 同意管理服务
public class ConsentService
{
    public bool HasConsent(int userId, string consentType)
    {
        return _db.ConsentLogs
            .Where(c => c.UserId == userId && c.ConsentType == consentType)
            .OrderByDescending(c => c.ConsentDate)
            .FirstOrDefault()?.ConsentStatus ?? false;
    }
    
    public void UpdateConsent(int userId, string consentType, bool status)
    {
        _db.ConsentLogs.Add(new ConsentLog
        {
            UserId = userId,
            ConsentType = consentType,
            ConsentStatus = status,
            ConsentDate = DateTime.Now
        });
        _db.SaveChanges();
    }
}

3.3 数据删除(被遗忘权)

实现数据删除功能:

public class DataErasureService
{
    public void EraseUserData(int userId)
    {
        // 删除用户主表数据
        var user = _db.Users.Find(userId);
        if (user != null)
        {
            _db.Users.Remove(user);
        }
        
        // 删除关联数据
        _db.Orders.RemoveRange(_db.Orders.Where(o => o.UserId == userId));
        _db.ConsentLogs.RemoveRange(_db.ConsentLogs.Where(c => c.UserId == userId));
        _db.AuditLogs.RemoveRange(_db.AuditLogs.Where(a => a.UserId == userId));
        
        // 异步删除其他系统数据
        _messageQueue.Publish("user_deleted", userId);
        
        _db.SaveChanges();
    }
}

3.4 数据可携权

实现数据导出功能:

public class DataPortabilityService
{
    public byte[] ExportUserData(int userId)
    {
        var user = _db.Users
            .Include(u => u.Orders)
            .Include(u => u.ConsentLogs)
            .FirstOrDefault(u => u.Id == userId);
        
        if (user == null)
            throw new NotFoundException();
        
        var data = new
        {
            User = new { user.Id, user.Email, user.CreatedAt },
            Orders = user.Orders.Select(o => new { o.Id, o.Amount, o.OrderDate }),
            Consents = user.ConsentLogs.Select(c => new { c.ConsentType, c.ConsentStatus })
        };
        
        return Encoding.UTF8.GetBytes(JsonSerializer.Serialize(data));
    }
}

四、数据本地化

4.1 数据本地化概述

数据本地化要求数据存储在特定地理区域内:

graph TD A[数据本地化要求] --> B[中国: 数据必须存储在中国境内] A --> C[欧盟: 数据必须存储在欧盟境内] A --> D[印度: 数据必须存储在印度境内] A --> E[巴西: 数据必须存储在巴西境内]

4.2 数据本地化策略

策略 描述 适用场景
本地部署 在本地数据中心部署 严格本地化要求
区域云 使用区域云服务 中等本地化要求
数据复制 将数据复制到本地 需要访问全球数据
数据隔离 按区域隔离数据 多区域运营

4.3 数据本地化实现

public class DataLocalizationService
{
    public DbConnection GetConnection(string region)
    {
        var connectionString = region switch
        {
            "CN" => "Server=cn-db;Database=app;Trusted_Connection=True;",
            "EU" => "Server=eu-db;Database=app;Trusted_Connection=True;",
            "US" => "Server=us-db;Database=app;Trusted_Connection=True;",
            _ => "Server=default-db;Database=app;Trusted_Connection=True;"
        };
        
        return new SqlConnection(connectionString);
    }
    
    public async Task MigrateUserData(int userId, string targetRegion)
    {
        var sourceConnection = GetConnection("US");
        var targetConnection = GetConnection(targetRegion);
        
        var userData = await sourceConnection.QuerySingleAsync<User>("SELECT * FROM users WHERE id = @id", new { id = userId });
        
        await targetConnection.ExecuteAsync(
            "INSERT INTO users (id, username, email) VALUES (@id, @username, @email)",
            userData
        );
        
        await sourceConnection.ExecuteAsync("DELETE FROM users WHERE id = @id", new { id = userId });
    }
}

五、审计日志

5.1 审计日志设计

-- 审计日志表
CREATE TABLE audit_logs (
    id BIGINT PRIMARY KEY AUTO_INCREMENT,
    event_type VARCHAR(50),
    user_id INT,
    user_ip VARCHAR(50),
    resource_type VARCHAR(50),
    resource_id BIGINT,
    action VARCHAR(50),
    before_data JSON,
    after_data JSON,
    timestamp DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY (user_id) REFERENCES users(id)
);

-- 审计日志索引
CREATE INDEX idx_audit_user ON audit_logs(user_id);
CREATE INDEX idx_audit_resource ON audit_logs(resource_type, resource_id);
CREATE INDEX idx_audit_timestamp ON audit_logs(timestamp);

5.2 审计日志记录

public class AuditService
{
    public void LogEvent(AuditEvent auditEvent)
    {
        _db.AuditLogs.Add(new AuditLog
        {
            EventType = auditEvent.EventType,
            UserId = auditEvent.UserId,
            UserIp = auditEvent.UserIp,
            ResourceType = auditEvent.ResourceType,
            ResourceId = auditEvent.ResourceId,
            Action = auditEvent.Action,
            BeforeData = auditEvent.BeforeData != null ? JsonSerializer.Serialize(auditEvent.BeforeData) : null,
            AfterData = auditEvent.AfterData != null ? JsonSerializer.Serialize(auditEvent.AfterData) : null
        });
        _db.SaveChanges();
    }
}

public class AuditEvent
{
    public string EventType { get; set; }
    public int UserId { get; set; }
    public string UserIp { get; set; }
    public string ResourceType { get; set; }
    public long ResourceId { get; set; }
    public string Action { get; set; }
    public object BeforeData { get; set; }
    public object AfterData { get; set; }
}

5.3 审计日志查询

public class AuditQueryService
{
    public List<AuditLog> GetUserAuditLogs(int userId, DateTime startDate, DateTime endDate)
    {
        return _db.AuditLogs
            .Where(a => a.UserId == userId && a.Timestamp >= startDate && a.Timestamp <= endDate)
            .OrderByDescending(a => a.Timestamp)
            .ToList();
    }
    
    public List<AuditLog> GetResourceAuditLogs(string resourceType, long resourceId)
    {
        return _db.AuditLogs
            .Where(a => a.ResourceType == resourceType && a.ResourceId == resourceId)
            .OrderByDescending(a => a.Timestamp)
            .ToList();
    }
}

六、数据泄露响应

6.1 数据泄露检测

public class DataBreachDetectionService
{
    public async Task DetectBreaches()
    {
        var suspiciousActivities = _db.AuditLogs
            .Where(a => a.EventType == "DataAccess" && a.Timestamp > DateTime.Now.AddMinutes(-5))
            .GroupBy(a => a.UserId)
            .Where(g => g.Count() > 100)
            .Select(g => g.Key)
            .ToList();
        
        foreach (var userId in suspiciousActivities)
        {
            await _notificationService.SendAlert(userId, "异常数据访问");
            await _auditService.LogEvent(new AuditEvent
            {
                EventType = "SecurityAlert",
                UserId = userId,
                Action = "SuspiciousActivity"
            });
        }
    }
}

6.2 数据泄露响应流程

flowchart TD A[发现数据泄露] --> B[评估影响] B --> C[通知监管机构] C --> D[通知受影响用户] D --> E[调查原因] E --> F[修复漏洞] F --> G[更新安全策略] G --> H[记录报告]

七、GDPR合规检查清单

7.1 数据处理

  • 是否有合法的数据处理依据?
  • 是否有隐私政策?
  • 是否获得用户同意?

7.2 数据主体权利

  • 是否支持数据访问?
  • 是否支持数据更正?
  • 是否支持数据删除?
  • 是否支持数据导出?

7.3 数据安全

  • 数据是否加密?
  • 是否有访问控制?
  • 是否有审计日志?
  • 是否有数据备份?

7.4 数据跨境

  • 数据是否跨境传输?
  • 是否有适当的保障措施?
  • 是否遵守数据本地化要求?

八、总结

GDPR合规是处理欧盟公民数据的基本要求,数据本地化是许多国家的法规要求。通过合理设计数据处理流程、实现数据主体权利、建立审计日志,能够满足合规要求,保护用户数据隐私。