ClouisleClouisle

登录与账户安全

完成注册、邮箱验证、密码恢复、TOTP 与 SSO 登录并配置登录保护

Clouisle 的认证流程由站点设置决定:密码、邮箱验证、管理员审批、人机验证、强制改密、TOTP 与 SSO 可能同时生效。本页按使用顺序说明每个环节的默认值、失败结果与恢复路径;站点级开关的完整清单见站点设置参考。

注册与邮箱验证

自助注册

  1. 前往登录页 https://your-domain.com,点击注册。

  2. 填写注册表单:

    字段约束
    用户名必填、全局唯一、最多 50 字符
    邮箱必填、全局唯一、需为合法邮箱地址
    密码按站点密码策略校验(默认至少 8 位,见密码要求)
    确认密码与密码一致
  3. 若开启人机验证,点击点击验证您是真人完成验证。

  4. 若开启「注册需同意条款」,勾选用户协议与隐私政策。

  5. 点击注册提交。

提交后的结果取决于站点设置:

站点设置默认值提交后行为
allow_registrationtrue关闭后注册入口返回 5000(registration_disabled)
require_approvaltrue开启时账户为待审批(approval_status=pending、is_active=false),管理员收到全局通知;审批前无法登录
email_verificationtrue开启时须先验证邮箱才能登录
enable_captchafalse开启时注册页显示点击式人机验证
require_terms_acceptance_on_registerfalse开启时必须勾选条款
force_password_change_first_loginfalse开启时新用户首次登录被要求立即改密

站点中第一个注册的用户会绕过全部限制:直接激活、邮箱标记为已验证,并被赋予 Super Admin 角色。因此请先完成首个管理员的注册,再开放注册。

Clouisle 没有邀请注册流程。账户来自自助注册、管理员创建(用户管理)或 SSO 自动创建(SSO)。

注册与邮箱验证
注册与邮箱验证

邮箱验证

  • 验证邮件由 SMTP 发送,未配置 SMTP(smtp_enabled=false)时发送会失败并返回 5007(smtp_not_configured)。
  • 邮件包含 6 位验证码和验证链接,有效期 10 分钟(Redis 中 600 秒)。
  • 重新发送的冷却时间为 60 秒(同一邮箱 + 用途),冷却未到返回 5008 并带 remaining_seconds。
  • 验证码错误返回 5005,链接/验证码过期返回 5006。
  • 未验证邮箱登录会返回 5004,登录页会直接切到验证步骤并自动重发一封验证码。

登录方式

密码登录

  1. 前往登录页,输入用户名或邮箱(含 @ 时按邮箱匹配,邮箱大小写不敏感;不含 @ 时按用户名精确匹配)。
  2. 输入密码。
  3. 若开启人机验证,点击点击验证您是真人。
  4. 点击登录。

登录请求依次通过这些关卡,任何一步失败都会中断后续流程:

  1. SSO-only 模式:sso_enabled=true 且 sso_allow_password_login=false 时,密码登录返回 6306(password_login_disabled)。
  2. 人机验证(开启时)。
  3. 账户存在性:账号不存在与密码错误返回同一个 2003(incorrect_email_or_password),不泄露账号是否存在。
  4. 锁定状态:仍在锁定期返回 5300(account_locked),并带 remaining_seconds。
  5. 本地密码存在性:SSO 自动创建、没有本地密码的账户无法密码登录,同样返回 2003。
  6. 密码校验:失败时返回 2003 并带 remaining_attempts;达到阈值转为锁定(见账户锁定)。
  7. 账户状态:被停用返回 2004(inactive_user),待审批返回 2004(pending_approval_user)。
  8. TOTP:已绑定 TOTP 时返回 requires_totp=true 与 5 分钟有效的临时令牌,进入第二步验证。
  9. 管理员强制 TOTP:站点设置 require_totp=true 且用户未绑定 TOTP 时,返回 requires_totp_setup=true 与 30 分钟有效的临时令牌,前端跳转 /totp-setup 完成绑定。
  10. 邮箱验证(开启时;超级管理员豁免该检查)。
  11. 密码过期/强制改密:需要改密时响应仍返回令牌,但带 force_password_change=true 与 reason(expired 表示已过期,force 表示被要求),前端跳转 /change-password?reason=...。

登录成功后,失败计数与锁定状态会被清零,并刷新 last_login。

SSO 单点登录

若组织配置了 SSO,可使用企业凭据登录。

  1. 前往登录页,点击 SSO 提供商按钮(按钮文案取自提供商的 button_text,如「使用 Google 继续」)。
  2. 在身份提供商处完成认证。
  3. 自动跳转回 Clouisle 并登录。

首次 SSO 登录:

  • 邮箱匹配开启(sso_match_by_email,默认开启)且邮箱已存在时,SSO 连接会关联到该账户。
  • 否则在允许自动创建时新建账户。新账户没有本地密码、邮箱视为已验证,并按配置进入待审批状态。

支持 OAuth2/OIDC、SAML 2.0 与 CAS。配置与排查详见 SSO 配置。

关闭 sso_allow_password_login 会把站点切换成 SSO-only。切换前请确认至少一个超级管理员已完成 SSO 绑定,否则可能无人能登录后台。

首次登录

首次成功登录后:

  1. 欢迎界面:显示欢迎消息。
  2. 资料设置:完善个人资料(可选)。
  3. 团队分配:可能被加入默认团队(default_team_id,角色为 default_team_role,默认 member)。
  4. 仪表板访问:普通用户进入平台界面,管理员还会看到管理入口。

登录保护

人机验证

开关为 enable_captcha(默认关闭),作用于登录与注册两个表单。它验证的是一次真实的点击+指针轨迹,而不是输入文字。

  • 挑战与凭证在 Redis 中保存 300 秒(5 分钟),且一次性使用。
  • 校验失败返回 5303(captcha_invalid),缺少凭证返回 5302(captcha_required);前端在失败后会自动重新拉取一个新挑战。
  • 登录页只在填写了用户名与密码后才加载验证码,因此打开页面时看不到它是正常的。

账户锁定

失败计数是按账户保存在用户记录上的(failed_login_attempts + locked_until),没有滚动时间窗:

  • max_login_attempts 默认 5:累计到 5 次立即锁定。
  • lockout_duration_minutes 默认 15:锁定期间即使密码正确也会被拒(5300)。
  • 未达阈值时,错误响应会带 remaining_attempts,可据此提示剩余次数。
  • 计数不会随时间自动清零:要么登录成功,要么锁定到期后的下一次登录尝试(此时才归零)。
  • 触发锁定时会向用户发送 security.account_locked 高优先级通知,内容含锁定分钟数。

按 IP 的失败计数(Redis 键 login:attempts:ip:<ip>,TTL 3600 秒)在代码中只有写入/读取函数,没有任何调用方,因此当前版本并未按 IP 限速。锁定只发生在账户维度。

登录异常检测

系统在 Redis 中记录每个账户最近登录过的 IP 与 User-Agent(各最多 10 条,保留 30 天):

  • 出现过历史记录后,从新 IP 或新设备登录会触发 security.login_anomaly 高优先级通知,内容包含 IP、时间与 User-Agent。
  • 首次登录(还没有历史记录)不会告警,避免每次新账号都误报。
  • Redis 不可用时该检测会被跳过,登录流程不受影响。

密码管理

密码要求

要求默认值设置键
最小长度8 个字符min_password_length(站点设置界面允许 6–32)
大写字母至少 1 个(A-Z)require_uppercase
数字至少 1 个(0-9)require_number
特殊字符不要求require_special_char
小写字母无此开关—
不可复用不能与最近 5 个历史密码相同password_history_count
最小保留期0 天(可立即再改)password_min_age_days

没有字典/弱密码检查,也没有密码强度指示器——校验结果以字段错误的形式返回。另有一条 bcrypt 限制:超过 72 字节的部分被忽略,所以超长密码的尾部字符不参与校验。

有效密码示例(满足默认策略):

MySecure#Pass2026!

无效密码示例:

❌ 12345678       (无大写字母)
❌ abcdefgh       (无数字)
❌ Pass123        (仅 7 位,短于默认 8 位)

修改密码

  1. 打开个人设置(头像菜单)→ 账户安全 标签页。
  2. 找到修改密码区域,填写当前密码、新密码、确认新密码。
  3. 点击更新密码。

后端行为(POST /api/v1/users/me/change-password):

  • 当前密码错误返回 2003(current_password_incorrect)。
  • 未满足最小保留期(password_min_age_days)返回 5306,并带还需等待的天数。
  • 不符合策略或命中历史密码返回 1001,errors.new_password 中给出逐条原因(如 password_recently_used)。
  • 成功后刷新 password_changed_at、按策略重算过期时间、清除强制改密标记,并发送 security.password_changed 高优先级通知。

强密码建议:混合多种字符类型、长度至少 12 位、避免个人信息、使用密码管理器。

重置忘记的密码

前置条件:必须已配置 SMTP(smtp_enabled=true)。未配置时「忘记密码」直接返回 5007(smtp_not_configured)。

  1. 前往登录页,点击忘记密码?。
  2. 输入邮箱地址并点击发送重置邮件。为防枚举,无论邮箱是否存在都会返回成功。
  3. 查收邮件,两种方式任选:
    • 点击邮件中的重置链接(跳转 /reset-password?token=...);
    • 或在页面上展开或手动输入验证码,填入邮件里的 6 位验证码。
  4. 输入新密码并确认,点击重置密码。
  5. 用新密码登录。
  • 验证码/链接有效期 10 分钟;重发冷却 60 秒(5008)。
  • 验证码错误返回 5005,链接无效或过期返回 5006。
  • 重置不要求当前密码(凭证本身就是授权),但同样校验密码策略与历史;成功后账户的失败计数与锁定状态会被清除。

密码过期

若管理员启用密码过期策略(默认关闭):

设置键默认值含义
password_expiration_enabledfalse策略总开关
password_expiration_days90密码有效天数
password_expiration_warning_days7到期前提醒窗口
password_history_count5历史密码保留数量
password_min_age_days0改密最短间隔

豁免对象:SSO 账户(auth_source != "local")、被单独标记豁免的用户(password_expiration_exempt)以及超级管理员,均不参与过期与强制改密。

时间线:

  • 每日 08:00 运行过期检查:距到期正好 7 / 3 / 1 天时发送 password.expiring 提醒;已过期则发送 password.expired 并设置强制改密标记(同一用户每天最多一次提醒)。
  • 登录时若已过期,响应带 force_password_change=true 与 reason=expired,前端跳转 /change-password?reason=expired。
  • 个人设置的账户安全标签页会展示密码过期时间;已过期显示红色告警,剩余不足 7 天显示黄色预警(该阈值在前端固定为 7 天)。

TOTP 双因素认证

设置 TOTP

  1. 打开个人设置 → 账户安全 标签页,点击启用双因素认证。
  2. 向导第一步说明双因素认证的作用;第二步展示二维码(issuer 为 Clouisle),用身份验证器(Google Authenticator、Authy、Microsoft Authenticator、1Password 等)扫码,或手动输入密钥。
  3. 输入身份验证器当前的 6 位验证码完成校验(校验窗口为 ±1 个周期,即 ±30 秒)。
  4. 保存一次性备份码:向导一次生成 10 个,格式 XXXX-XXXX,可下载(clouisle-backup-codes.txt)或复制。
  5. 点击完成。

接口先调用 POST /api/v1/totp/setup 生成密钥、二维码与备份码,此时尚未启用;POST /api/v1/totp/enable 校验验证码后才真正启用。已启用时再次调用 setup/enable 返回 5314(totp_already_enabled);缺少待启用密钥时 enable 返回 5315(totp_setup_expired)。

TOTP 设置向导
TOTP 设置向导

TOTP 密钥用 SECRET_KEY 派生的密钥加密后存储。更换 SECRET_KEY 会导致所有已绑定的 TOTP 密钥无法解密,用户只能由管理员解绑后重新绑定。

使用 TOTP 登录

  1. 输入用户名和密码,后端返回 requires_totp=true 与 5 分钟有效的临时令牌。
  2. 输入身份验证器中的 6 位验证码(或点击使用备份码改输备份码)。
  3. 点击验证。成功后临时令牌被替换为正式登录令牌。

验证失败返回 5311(totp_invalid);被限速时返回 5312(totp_rate_limited)并带 seconds,前端直接提示剩余等待秒数。限速规则:自首次失败起 300 秒窗口内累计 5 次失败即锁定 900 秒(15 分钟);成功验证后计数清零。

备份码

  • 一次生成 10 个,格式 XXXX-XXXX,每个只能使用一次,服务端只保存哈希。
  • 账户安全标签页显示剩余备份码数量(界面文案为 剩余 {count} 个备份码)。
  • 点击重新生成备份码并输入当前 6 位验证码,即可作废旧码、生成新的一批(旧备份码立即失效)。

禁用 TOTP 与管理员操作

  • 用户自行禁用:点击禁用双因素认证,在确认框中同时提供账户密码与当前验证码(或备份码)——两项都必须通过校验,密码错误返回 2003,验证码错误返回 5311。
  • 管理员解绑:POST /api/v1/admin/totp/users/{user_id}/disable 可直接为某用户关闭 TOTP,用于用户丢失验证器与备份码的场景(需要 admin:dashboard:access 权限)。
  • 强制全员 TOTP:站点设置 require_totp=true 时,未绑定用户登录会被重定向到 /totp-setup 完成绑定,不绑定则无法进入系统。

会话管理

会话时长

  • 会话是无状态 JWT,有效期取 session_timeout_days(默认 30 天),没有空闲超时、也没有「记住我」选项。
  • 令牌保存在浏览器 localStorage 的 access_token 中,随请求以 Authorization: Bearer <token> 发送。

单会话模式

开启 single_session 后,新登录会把上一个令牌写入 Redis 黑名单并覆盖会话记录。

已知限制

认证链路只检查 Redis 黑名单,而登录时写入的黑名单条目 TTL 只有 5 秒;用于读取会话记录的 get_user_session 目前没有调用方。因此单会话模式实际只在约 5 秒内拒绝旧令牌,之后旧令牌仍可继续使用到其过期。不要把单会话模式当作踢出会话的安全手段。

注销

  1. 点击右上角个人资料图标。
  2. 选择退出登录。
  3. 跳转到登录页。

后端的行为是:把当前令牌加入 Redis 黑名单(TTL 5 秒)并清除会话记录;JWT 本身无状态,已复制到别处的同一令牌在 5 秒后仍会被接受,直到自身过期。真正生效的阻断手段是修改密码(并配合单会话)、停用账户或缩短 session_timeout_days。

账户安全

安全通知

以下事件会产生 security.* / password.* 站内通知:

事件类型触发时机级别
security.password_changed修改密码成功高
security.account_locked连续失败触发锁定高
security.login_anomaly新 IP / 新设备登录高
password.force_change管理员要求下次登录改密高
user.password_reset管理员为用户设置了新密码中
password.expiring / password.expired到期前 7/3/1 天 / 已过期中

定期查看通知中心 是发现未授权访问最直接的方式。

账户被盗用

若怀疑未授权访问:

  1. 立即修改密码。注意这不会作废已签发的 JWT(见注销),也不会影响已有的 API Key。
  2. 启用 TOTP,或重新生成备份码。
  3. 查看登录通知中是否有陌生 IP / 设备,并在API 密钥列表中停用可疑密钥。
  4. 联系管理员停用账户——is_active=false 会在认证阶段立刻拒绝该账户的所有请求,是唯一能立即止血的手段。轮换 SECRET_KEY 同样能让全部 JWT 失效,但会导致所有已绑定的 TOTP 密钥无法解密,请谨慎使用。

管理员设置新密码

管理员在用户管理中可以直接为用户设置新密码(PUT /api/v1/admin/users/{id} 带 password):

  1. 管理员设置新密码(会按密码策略校验,但不检查历史密码)。
  2. 系统向该用户发送 user.password_reset 通知——不会发送含临时密码的邮件,新密码需要管理员通过安全渠道另行告知。
  3. 用户用新密码登录后应立即自行修改。

配套的管理员操作:强制修改密码(POST /api/v1/admin/users/{id}/force-password-change,用户下次登录必须改密)、重置过期计时(重置 password_changed_at)、免除过期策略(password_expiration_exempt)。

故障排除

无法访问登录页

  1. 检查网络连接与 URL 是否正确。
  2. 尝试其他浏览器并清除缓存与 Cookie。
  3. 确认 site_url / 前端地址配置正确(SSO 回调也会用到)。
  4. 联系管理员。

登录提示用户名或密码错误

账号不存在、密码错误、SSO 账户尝试密码登录,返回的都是同一个 2003——这是反枚举设计,不代表系统故障。

  1. 确认使用的是用户名(精确匹配)或邮箱(大小写不敏感)。
  2. 若账户由 SSO 创建且从未设置本地密码,请改用 SSO 登录。
  3. 提示中若带 remaining_attempts,注意剩余尝试次数。
  4. 使用忘记密码重置。

账户已被锁定

  1. 等待锁定自动到期(默认 15 分钟)后重新登录,此时失败计数会归零。
  2. 管理员的激活/编辑操作不会清除 locked_until,没有「立即解锁」按钮;若急需恢复访问,可走忘记密码重置流程——重置成功会同时清除失败计数与锁定状态。
  3. 若反复被锁定,检查是否有旧脚本在重试错误密码。

未收到验证/重置邮件

  1. 确认 smtp_enabled=true 且 SMTP 参数正确——未配置时接口直接返回 5007。
  2. 检查垃圾邮件文件夹并等待几分钟。
  3. 注意 60 秒重发冷却(5008 会给出剩余秒数)。
  4. 确认邮箱地址与账户上的邮箱一致。

未收到验证码导致的邮箱未验证

登录时返回 5004 会直接进入验证步骤并自动重发一封验证码;页面上的重新发送按钮受 60 秒冷却限制。

由于管理端没有「标记邮箱已验证」的开关,若用户始终收不到邮件,请先让管理员确认 SMTP 配置(未配置时发送接口直接 5007);仍不可用时,可临时关闭 email_verification 让该用户先登录,待邮件通道恢复后再重新开启。

TOTP 无法验证

  1. 检查设备时间是否自动同步(±30 秒窗口)。
  2. 被限速时按提示等待,最多 15 分钟。
  3. 改用一次性备份码登录。
  4. 备份码用尽时联系管理员解绑后重新绑定。

被要求修改密码

说明 force_password_change 已置位(密码过期,或管理员强制)。在 /change-password 页面输入当前密码与新密码即可;改密成功后标记自动清除。

SSO 登录失败

  1. 确认使用的提供商与账户状态(停用/待审批会跳转到 /sso-callback 并显示对应提示)。
  2. 检查提供商配置与回调地址(详见 SSO 配置)。
  3. 清除浏览器 Cookie 后重试,或改用密码登录(若站点允许)。

最佳实践

✅ 推荐

  • 使用强而唯一的密码,并开启 TOTP。
  • 使用密码管理器,不在多处复用同一密码。
  • 保持邮箱地址有效,它是密码恢复的唯一通道。
  • 处理安全通知,而不是清空通知列表。
  • 优先用 SSO 登录,减少密码暴露面。

❌ 避免

  • 与他人共享账户或密码。
  • 在公共设备上保持登录(退出只影响本机令牌,且见注销的限制)。
  • 在共享设备上关闭 TOTP。
  • 忽略 security.login_anomaly 告警。

相关页面

这篇文章对你有帮助吗?

本页目录