7.3 KiB
7.3 KiB
06.1 - 云同步(安全进阶):服务端账户/凭据与策略实现方案
1. 目标
为 04-*(基础能力)与 06-*(落盘策略)提供服务端底层安全实现的具体方案,确保账户密码存储、Token 管理、二次认证及安全策略下发具备生产级安全性。
2. 账户与密码安全存储
服务端不应存储明文密码,需采用强哈希算法进行加盐处理。
存储结构 (Users 表)
UserId:Guid(主键)UserName:string(唯一索引)PasswordHash:string(存储哈希后的结果)PasswordSalt:string(若哈希算法自带 Salt,如 BCrypt/Argon2,则可省略)Role:string(用户角色,如 admin/user)CreatedAtUtc:DateTimeUpdatedAtUtc:DateTime
哈希算法建议
- 算法:
Argon2id(推荐) 或BCrypt。 - 配置: 迭代次数、内存占用、并行度应符合 OWASP 最新建议。
3. Token 管理 (JWT)
采用 JSON Web Token (JWT) 作为会话凭据,并支持细粒度权限控制。
Token 结构 (Payload)
{
"sub": "UserId",
"name": "UserName",
"role": "Role",
"perms": ["tasks:read", "sync:write", "policy:read"],
"iat": 1712000000,
"exp": 1712003600,
"iss": "Hua.Todo.Server",
"aud": "Hua.Todo.Client",
"isStepUp": false // 是否通过了二次认证
}
校验逻辑
- 每次请求需携带
Authorization: Bearer {token}。 - 服务端验证签名、有效期(exp)、签发者(iss)及受众(aud)。
- 权限校验:中间件检查
perms声明是否包含当前接口所需的权限。
4. 二次认证与会话提升 (Step-up)
针对高风险操作(如 sync:write、policy:write),要求会话必须处于“提升状态”。
流程设计
- 触发: 客户端调用
/sync,服务端检查 Token 的isStepUp声明。 - 拒绝: 若
isStepUp == false,返回403 SECOND_FACTOR_REQUIRED。 - 挑战: 客户端调用
/auth/step-up,提供二次认证凭据(如再次输入密码,或 TOTP 验证码)。 - 提升: 验证成功后,服务端颁发一个新的 Token,其中
isStepUp: true,且有效期较短(如 30 分钟)。 - 重试: 客户端携带新 Token 重新发起请求。
5. 安全策略 (Security Policy) 存储与下发
安全策略决定了客户端的“落盘”行为及二次认证频率。
策略定义 (SecurityPolicies 表)
Id:int(主键)UserId:Guid(外键)AllowPersist:bool(是否允许客户端持久化任务数据)AllowSync:bool(是否允许该用户同步)SecondFactorExpiryMinutes:int(二次认证状态保持时长,默认 30)IsTrustedDeviceOnly:bool(是否仅限受信任终端)
下发逻辑
- 客户端通过
GET /security/policy获取。 - 策略应与
UserId绑定,允许管理员针对不同用户/角色进行差异化配置。
6. 审计日志 (Audit Logs)
记录关键安全事件,便于追溯。
- 登录成功/失败(记录 IP、终端信息)。
- 高风险操作尝试(是否通过二次认证)。
- 安全策略变更。
8. 客户端 UI 与交互设计
8.1 二次认证 (Step-up) 交互流程
- 静默拦截: 当用户触发高风险操作(如点击“立即同步”且 Token 已过期或未提升)时,客户端拦截请求并检测到
403 SECOND_FACTOR_REQUIRED。 - 弹出对话框: 弹出“安全验证”模态框。
- 标题: 需要二次认证。
- 描述: “为了保护您的数据安全,执行此操作需要验证身份。”
- 输入: 密码输入框(或 TOTP 验证码输入框)。
- 操作: [取消] [验证并继续]。
- 状态保持: 验证成功后,UI 应显示短暂的“验证成功”提示,并自动重试刚才被拦截的操作。
8.2 客户端 UI (针对普通用户)
在客户端“设置 -> 云同步 -> 安全”路径下:
- 落盘策略 (AllowPersist):
- 展示: 状态开关(Toggle)。
- 交互:
- 若由服务端强制禁止,开关应为禁用状态(Disabled),并附带说明:“受服务端策略限制,当前终端禁止落盘”。
- 若允许修改,关闭开关时应弹出强提醒:“关闭后,所有本地任务数据将被立即清除,退出应用后数据将不再保留。确定继续吗?”
- 二次认证频率:
- 展示: 显示当前二次认证的有效期(如 30 分钟)。
8.3 “不可落盘”模式下的视觉提示
当 allowPersist == false 时:
- 状态栏/标题栏: 增加“无痕模式”或“内存存储”小图标/文字提醒。
- 登录页: 增加提醒:“当前环境配置为禁止落盘,数据仅在本次运行期间有效”。
- 退出应用: 点击退出时,若有未同步数据,强提醒:“数据未同步且本地禁止落盘,退出将导致数据丢失。确定退出吗?”
9. 服务端管理后台 (Admin Dashboard)
为了避免直接操作数据库,服务端需提供一套 Web 管理后台,供管理员维护账户、权限与安全策略。
9.1 工程位置与实现
- 宿主项目: Hua.Todo.Host
- 实现方式:
- 前端采用 Vue 3 + Vite 开发。
- 静态资源在构建后嵌入到
Hua.Todo.Host的wwwroot目录或作为内嵌资源。 - 后端通过 ASP.NET Core 的
UseStaticFiles()托管,并确保/admin路由指向前端入口。
9.2 系统初始化 (Bootstrap)
- 触发条件: 当检测到数据库中无任何用户时,访问
/admin自动跳转至/admin/bootstrap。 - 功能: 创建首个“超级管理员”账号。
- UI: 简单的表单(用户名、密码、确认密码)。
9.3 用户管理 (User Management)
- 用户列表: 展示所有已注册用户(UserId, UserName, Role, CreatedAt)。
- 创建用户: 管理员手动添加用户(用于内部系统或受控注册)。
- 重置密码: 为忘记密码的用户生成临时密码或直接重设(需审计记录)。
- 禁用/删除: 软删除或禁用账号。
9.4 安全策略配置 (Security Policy Management)
- 全局策略: 设置系统默认的
allowPersist、allowSync及SecondFactorExpiry。 - 单用户覆盖: 在用户详情页中,管理员可以针对特定高风险用户/终端覆盖全局策略(例如:对特定外包人员账号强制
allowPersist = false)。
9.5 会话与凭据管理 (Session Management)
- 在线会话查看: 展示当前所有有效的 Token/会话(记录 IP、最后活跃时间、是否已提升权限)。
- 强制下线 (Revoke): 管理员可一键吊销特定用户的所有 Token(将其加入黑名单)。
9.6 审计日志查看器 (Audit Log Viewer)
- 过滤查询: 按时间、用户、事件类型(登录、同步、策略变更)过滤。
- 高亮显示: 对“二次认证失败”、“异常 IP 登录”等敏感事件进行红色高亮。
10. 约束与风险
- Token 吊销: 默认 JWT 是无状态的。若需支持强制下线,需引入 Redis/DB 黑名单。
- HTTPS: 所有安全通信必须基于 TLS,防止中间人攻击窃取 Token。
- 暴力破解: 需在
POST /auth/login接口增加限流(Rate Limiting)机制。