隐私设计(Privacy by Design)
概述
从项目之初就将隐私保护融入软件架构,而非事后补救。本技能在设计数据库、API 和用户流程时,应用隐私设计原则(GDPR 第 25 条、Cavoukian 框架)。保护真实用户数据,建立信任基础。
适用场景
- 构建采集个人数据的应用(姓名、邮箱、位置、偏好)
- 设计数据库 Schema、API 或认证流程
- 涉及表单、用户账户、数据分析或第三方集成
- 部署上线前——验证隐私控制措施
法律框架
GDPR(欧盟) — 主要参考依据。第 25 条要求"从设计和默认层面保护数据"。适用于欧盟用户,通常也被全球采纳。
CCPA(加州) — 知情权、删除权、退出数据出售权。核心原则类似:最小化、透明披露、允许用户控制。
LGPD(巴西) — 与 GDPR 对齐。目的限制、必要性、透明度。适用于巴西用户。
按你所面向的最严格框架设计,通常也能满足其他框架的要求。
核心原则
1. 数据最小化
只采集严格必要的数据。每个字段都需要有明确的用途说明。避免"以后可能用得上"的心态。
2. 目的限制
记录每个数据点的采集目的。不得将数据用于用户未同意的用途。
3. 存储限制
定义保留期限。到期后自动删除或匿名化处理。永远不要默认永久保留数据。
4. 默认隐私
可选数据采集采用"主动加入"而非"主动退出"模式。敏感功能(数据分析、营销推送)默认关闭。不使用预勾选的同意框。
5. 端到端安全
静态数据和传输数据均加密。使用 RBAC(基于角色的访问控制)。记录敏感数据的访问日志以供审计。
6. 透明度
记录采集了哪些数据及原因。提供清晰的隐私政策。为用户提供便捷的数据访问和删除途径。
用户权利(GDPR)
确保从第一天起就可实现以下权利:
| 权利 | 需要构建的功能 |
|---|---|
| 访问权 | 提供返回用户所有数据的接口或流程 |
| 更正权 | 支持更新/修正数据 |
| 删除权 | 账户删除 + 数据清除(包括备份) |
| 可携权 | 以机器可读格式(JSON、CSV)导出数据 |
深入解析:为什么重要
数据最小化 — 数据越少 = 泄露影响越小、存储成本越低、合规越简单。每个字段都是一份责任。
目的限制 — 未经同意复用数据在 GDPR 下属于违法行为。在 Schema 或元数据中记录用途。
保留期限 — 无限期存储会增加风险并违反 GDPR。为每种数据类型定义 retention_days;自动化清理流程。
日志管理 — 日志经常泄露 PII(个人可识别信息)。对邮箱、ID、令牌做脱敏处理。使用结构化日志配合白名单机制。
第三方依赖 — 每个 SDK(数据分析、崩溃报告、广告)都可能将数据发送到其他地方。审计依赖项;加载前需获得用户同意。
代码示例
JavaScript/Node — 最小化用户模型
// 反面:以防万一,什么都采集
const user = { email, name, phone, address, birthdate, ipAddress, userAgent, ... };
// 正面:最小化,每项有明确用途
const user = {
email, // 用途:身份认证
displayName, // 用途:界面显示
createdAt, // 用途:账户年龄
};
JavaScript — 先获得同意再追踪
// 反面:先追踪,后询问
analytics.track(userId, event);
// 正面:先检查同意状态
if (userConsent.analytics) {
analytics.track(userId, event);
}
Python — 安全日志
# 反面:明文记录 PII
logger.info(f"User {user.email} logged in from {request.remote_addr}")
# 正面:脱敏或哈希标识符
logger.info(f"User {hash_user_id(user.id)} logged in")
# 或:logger.info("User login", extra={"user_id_hash": hash_id(user.id)})
SQL — 带用途和保留期的 Schema
-- 正面:在 Schema 中记录用途和保留期
CREATE TABLE users (
id UUID PRIMARY KEY,
email VARCHAR(255) NOT NULL, -- 用途:认证,保留期:账户存续期间
display_name VARCHAR(100), -- 用途:界面显示,保留期:账户存续期间
created_at TIMESTAMPTZ, -- 用途:审计,保留期:7 年
last_login_at TIMESTAMPTZ -- 用途:安全,保留期:90 天
);
-- 添加保留策略(PostgreSQL 示例)
-- 定时任务:90 天后匿名化/删除 last_login_at
API — 只返回必要字段
# 反面:返回完整用户对象
return jsonify(user) # 可能包含内部字段、哈希密码
# 正面:显式白名单
return jsonify({
"id": user.id,
"email": user.email,
"displayName": user.display_name,
})
常见陷阱
| 陷阱 | 解决方案 |
|---|---|
| 日志中包含邮箱、IP、令牌 | 对 PII 做脱敏;使用哈希 ID 或结构化日志 |
| 错误信息暴露数据 | 向客户端返回通用错误;详细信息记录在服务端日志 |
| 第三方 SDK 在获得同意前加载 | 同意后再加载分析/广告组件;使用同意管理平台 |
| 没有删除流程 | 从第一天起设计账户删除 + 数据清除功能 |
| 备份永久保留数据 | 备份纳入保留策略;加密备份 |
| 未获同意就使用 Cookie | 使用同意横幅;遵守 Do Not Track |
第三方审计
在引入涉及用户数据的依赖之前:
- 它采集或接收哪些数据?
- 数据发送到哪里(服务器、国家/地区)?
- 是在用户同意前还是同意后加载?
- 用户退出后能否禁用该功能?
- 它们的隐私政策是否与我们一致?
实现检查清单
构建涉及用户数据的功能时:
- 这些数据是否必要?能否用更少的数据实现目标?
- 是否已获得该用途的明确同意?
- 是否已加密(静态存储和传输过程)?
- 是否有保留/删除策略?
- 用户能否导出或删除自己的数据?
- 第三方服务是否已披露并获得同意?
- 日志中是否不含 PII?
- 备份是否纳入保留策略?
最佳实践
- ✅ 每个新数据字段都问一句"我们真的需要这个吗?"
- ✅ 从第一天起就设计删除和导出流程
- ✅ 尽可能对敏感标识符使用哈希或令牌化处理
- ✅ 在 Schema 或元数据中记录用途和保留期
- ❌ 不要明文记录密码、令牌或 PII
- ❌ 不要在未获得明确同意的情况下与第三方共享数据
- ❌ 不要假设"以后再加隐私保护"——这几乎不会发生
- ❌ 不要向客户端暴露堆栈跟踪或内部错误信息
适用时机
本技能适用于构建涉及个人数据采集、存储或处理的软件。在设计和实现阶段主动应用。
局限性
- 仅在任务明确匹配上述范围时使用本技能。
- 不要将输出视为对环境特定验证、测试或专家评审的替代。
- 如果缺少必要的输入、权限、安全边界或成功标准,请停下来请求澄清。