71 lines
3.5 KiB
Markdown
71 lines
3.5 KiB
Markdown
# WebAuthn 第二因素
|
||
|
||
WebAuthn 使用 Spring Security 官方过滤器、WebAuthn4J 校验和 JDBC 仓储。
|
||
PostgreSQL 保存 user handle、凭据公钥与签名计数等记录,不保存用户密码或认证器私钥。
|
||
AD 仍为用户与组权威;凭据按目录 authority + objectGUID 关联,用户名改名不会换主体。
|
||
|
||
## 登录与注册
|
||
|
||
1. `/signin` 使用原生表单 POST 验证 AD 密码,建立 `FACTOR_PASSWORD`。
|
||
2. `/signin/mfa`:没有凭据时注册 passkey;已有凭据时验证 passkey。
|
||
3. 注册只保存凭据,必须再次实际验证,才取得 `FACTOR_WEBAUTHN`。
|
||
4. `/signin/complete` 要求两种因素均在 10 分钟内有效;目前仅显示验证结果,尚不接受 Hydra challenge。
|
||
|
||
首次注册信任近期 AD 密码验证。已有凭据后的新增注册同时要求密码与 WebAuthn 因素;
|
||
本轮 UI 只提供首次注册与验证,不提供新增管理、删除或自助恢复入口。遗失所有 passkey
|
||
尚无自助登录途径;生产上线前需要另行确定恢复和初始注册政策,不能把数据库清空作为日常恢复方式。
|
||
注册和验证均要求认证器 user verification(例如 PIN 或生物识别)。
|
||
|
||
Spring Security 负责因素合并、会话轮换、退出和 CSRF。应用仅补目录主体与凭据所有权
|
||
限制、首次注册并发检查,以及 challenge 的 5 分钟服务端有效期和单次消费。
|
||
没有应用自建登录状态机或认证 Filter。上游 options Filter 位于授权 Filter 前,因而
|
||
这些检查在 RelyingPartyOperations 扩展点执行,不能仅靠 URL 授权规则。
|
||
|
||
## 本地数据库
|
||
|
||
```sh
|
||
# 密码从 shell 或外部权限为 0600 的 env 文件提供;不要写入版本库。
|
||
docker compose -p iam-login-dev -f compose.dev.yaml up -d
|
||
```
|
||
|
||
必须设置 `IAM_DEV_DB_PASSWORD`。PostgreSQL 仅发布在 `127.0.0.1:15432`,可用
|
||
`IAM_DEV_DB_PORT` 调整端口;数据保存在 Compose named volume 中。
|
||
普通 `down` 不删数据,**不要使用 `down -v`**,否则会删除已注册凭据。
|
||
|
||
应用额外配置:
|
||
|
||
```yaml
|
||
iam:
|
||
webauthn:
|
||
enabled: true
|
||
rp-id: laptop.tail7e769.ts.net
|
||
origin: https://laptop.tail7e769.ts.net:18082
|
||
spring:
|
||
datasource:
|
||
url: jdbc:postgresql://127.0.0.1:15432/iam_login
|
||
username: iam_login
|
||
password: ${IAM_DEV_DB_PASSWORD}
|
||
```
|
||
|
||
同时启用并配置 [AD](ad-login.md)。RP ID 不含协议与端口,origin 必须与浏览器实际
|
||
HTTPS 入口完全一致;改变 RP 域名后旧凭据不能直接在新域名使用。
|
||
凭据 schema 由 Flyway 管理,采用 Spring Security 7.1.1 官方 PostgreSQL 表结构,
|
||
增加主体名称唯一约束和凭据所有者索引。未启用 WebAuthn 时不创建 DataSource,AD-only
|
||
路径不需要数据库。数据库不可用时 MFA 失败,不降级为仅密码通过。
|
||
|
||
## 验证
|
||
|
||
JVM 回归使用 Testcontainers PostgreSQL 与模拟 AD;不会向真实 AD 提交测试密码。
|
||
浏览器用 Chromium 虚拟认证器产生真实注册/断言签名,再交给后端校验:
|
||
|
||
```sh
|
||
scripts/gradle-in-docker test
|
||
scripts/gradle-in-docker webauthnBrowserFixture
|
||
# 另一终端;测试夹具固定监听 localhost:18083,使用测试证书。
|
||
IAM_WEBAUTHN_FIXTURE=1 npm --prefix frontend run test:browser -- webauthn.spec.ts
|
||
```
|
||
|
||
测试专用启动类仅在 test classpath,不进入生产 JAR,也不提供生产调试 API。
|
||
真实用户的 passkey 注册、认证器兼容性和 Native 路径仍需独立验收;JVM/虚拟认证器通过
|
||
不能代替真实人类或 Native 验收。生产共享 PostgreSQL 的接入留在部署阶段。
|