首页
/ Front-End-Checklist 实战指南:构建符合 WCAG 2.2 SC 3.3.8 的无障碍认证流程(autocomplete、OTP 自动填充与 Passkey 路径)

Front-End-Checklist 实战指南:构建符合 WCAG 2.2 SC 3.3.8 的无障碍认证流程(autocomplete、OTP 自动填充与 Passkey 路径)

2026-09-04 23:16:53作者:胡易黎Nicole

本篇指南基于 Front-End-Checklist 仓库中的无障碍认证规则(rule.md),系统讲解如何设计登录、MFA 与账户恢复流程,使其兼容密码管理器、粘贴、OTP 自动填充与 Passkey,而不依赖用户的记忆或誊写能力。读完后,你将掌握:autocomplete 令牌(username webauthncurrent-passwordone-time-code)的正确用法、可直接复制的 HTML 与 React 代码示例、自动化与手动验证清单,以及 WCAG 2.2 SC 3.3.8 对"非记忆依赖路径"的具体要求。

规则定位与元信息

在本仓库的规则体系中,"Provide accessible authentication methods" 是一条高优先级、进阶难度的认证可访问性规则,核心断言只有一句话:

认证流程应避免不必要的认知测试,并支持密码管理器、粘贴、OTP 自动填充和 Passkey 等辅助机制。

规则元数据(优先级 high / 难度 advanced / 预计耗时 25 分钟)在两个文件中保持一致:技能入口 SKILL.md 的 frontmatter,以及规则正文 rule.md 的头部声明。技能文件还声明了它的适用边界:用于审查登录、注册、MFA、CAPTCHA、恢复与重新认证(re-auth)流程,且要求评估完整的认证路径(含错误处理与备用方式),而不只是主登录表单。

仓库中对应的完整规则定义位于 accessible-authentication.mdx,其 frontmatter 标注了三个分类维度(accessibility / security / html)、表单子分类,以及三条权威资料来源:

资料来源 类型 角色
WCAG 2.2 SC 3.3.8 Accessible Authentication (Minimum) wcag standard(标准依据)
W3C Understanding SC 3.3.8 wcag implementation(实现指导)
MDN HTML autocomplete attribute mdn reference(属性参考)

从 frontmatter 的 relatedRules 结构看,这条规则与四条相邻规则显式关联,构成一个"认证可访问性"审查簇:

核心原理:为什么"反认知测试"会同时提升安全

原文档给出的论点是:当存在可行的辅助路径时,认证不应依赖用户记忆、誊写或手工复现信息的能力。好的无障碍认证通常同时提升安全性——因为它与密码管理器、基于设备的验证和 Passkey 协作,而不是与它们对抗。

原文档列出了典型的"不必要的摩擦"模式:

  • 阻止粘贴(blocked paste);
  • 自研 OTP 输入组件,破坏了标准自动填充;
  • 要求誊写的 CAPTCHA;
  • 用"备份问题"式的记忆证明替代基于持有物(possession-based)的验证。

这些摩擦的实际代价包括:

  1. 认知障碍在用户做任何事情之前就先阻断了账户访问;
  2. 对密码管理器不友好会诱发更弱、被复用的密码;
  3. 语音输入、切换设备、纯键盘用户在被禁用复制/粘贴和自动填充时付出更多操作成本;
  4. 恢复流程和 MFA 步骤经常失败——哪怕主登录表单本身看起来没问题。

代码示例:密码管理器与 OTP 友好的字段

下面完整继承原文档的三段示例代码。第一段是登录 + OTP 场景的标准字段写法:

<!-- Better: password-manager and OTP-friendly fields -->
<label for="email">Email</label>
<input id="email" name="email" type="email" autocomplete="username webauthn">

<label for="password">Password</label>
<input
  id="password"
  name="password"
  type="password"
  autocomplete="current-password">

<label for="otp">Verification code</label>
<input
  id="otp"
  name="otp"
  inputmode="numeric"
  autocomplete="one-time-code">

三个字段各对应一个关键的 autocomplete 令牌:

  • autocomplete="username webauthn":用户名字段。webauthn 令牌(多令牌空格分隔是合法写法)提示浏览器"此用户标识可用于 Passkey/WebAuthn 注册与登录",让支持 WebAuthn 的浏览器把该用户与 Passkey 凭据关联起来,这是"非记忆依赖路径"的前置语义;
  • autocomplete="current-password":登录密码字段。密码管理器据此识别"这是要取回已存密码"的场景,与注册场景的 new-password 区分(后者在 password-field-security.mdx 中有进一步说明);
  • autocomplete="one-time-code" 配合 inputmode="numeric":一次性验证码字段。one-time-code 令牌是现代浏览器/OS 对 SMS 验证码与邮件代码自动填充的识别依据,inputmode="numeric" 则让移动端直接弹出数字键盘,减少误输入。

第二段是 React 组件写法,注意 autoCompleteinputMode 是 React 的驼峰属性名,且保留了单输入框而非拆分为六个格子:

function VerifyCodeField({
  onSubmit,
}: {
  onSubmit: (code: string) => void
}) {
  return (
    <form
      onSubmit={(event) => {
        event.preventDefault()
        const formData = new FormData(event.currentTarget)
        onSubmit(String(formData.get('otp') ?? ''))
      }}
    >
      <label htmlFor="otp">Enter the verification code</label>
      <input
        autoComplete="one-time-code"
        id="otp"
        inputMode="numeric"
        name="otp"
        type="text"
      />

      <button type="submit">Continue</button>
    </form>
  )
}

从源码结构看,这个示例刻意用 FormData 从整个表单取值,意味着提交逻辑不依赖具体的输入控件结构——即使未来浏览器改变 OTP 自动填充的注入方式(例如写入隐藏字段或触发 input 事件),new FormData(event.currentTarget) 仍能以标准方式拿到值。type="text" 而非 type="tel" 也是有意为之:文本类型对自动填充兼容面更广,数字键盘由 inputMode 单独控制。

第三段是"非记忆依赖替代路径"的最小呈现——两个并列按钮:

<!-- Better: offer a non-memory-dependent alternative -->
<button type="button">Continue with a passkey</button>
<button type="button">Email me a sign-in link</button>

Passkey(基于 WebAuthn 的凭据)与 magic link(邮件签到链接)分别对应"基于设备的证明"与"发送到可信邮箱"两种路径,二者都不要求用户记忆或誊写任何信息。

最佳实践一:支持辅助输入(assisted entry)

原文档要求认证流程必须与以下机制协同工作:

  • 密码管理器(password managers);
  • 粘贴的凭据与验证码(pasted credentials and codes);
  • 操作系统/浏览器 OTP 自动填充(OS/browser OTP autofill);
  • 可用时的 Passkey 或设备审批(device approval)。

并给出一条硬约束:不要把一个一次性验证码拆进会破坏标准自动填充的自定义组件中,除非你已在真实浏览器中验证过行为。

这条约束在仓库的相邻规则中有直接佐证。paste-inputs.mdx 明确列出了三类"阻止粘贴"的反模式,并给出对应的正面写法:

<!-- Incorrect: Prevents pasting -->
<input type="password" onpaste="return false;" placeholder="Confirm Password">

<!-- Correct: Default behavior allows pasting -->
<label for="confirm-password">Confirm Password</label>
<input type="password" id="confirm-password" name="confirm-password">

<!-- Incorrect JavaScript -->
<script>
  document.querySelector('#email').addEventListener('paste', (e) => {
    e.preventDefault(); // Don't do this
  });
</script>

该规则同样以 WCAG 2.2 SC 3.3.8 为第一来源,其给出的理由链与本篇一致:阻止粘贴会劝退使用长而唯一的密码管理器生成密码;精细运动控制受限的用户难以准确敲入长字符串;粘贴还降低了 IBAN、订单号等关键字段的键入错误率。因此"支持粘贴"与"支持自动填充"应视为同一项认证可访问性要求的两个侧面。

最佳实践二:至少一条不依赖记忆的路径

原文档要求:在登录、MFA、恢复三个环节中,至少有一条可行路径不依赖认知功能测试(cognitive function test)。被点名的合格路径有四类:

路径 机制 用户依赖
Passkey WebAuthn 凭据 + 设备生物识别/PIN 持有可信设备
可信设备审批 推送审批(device approval) 持有第二设备
Magic link 一次性链接发送到邮箱/手机 持有可信邮箱
密码管理器辅助 正确 autocomplete 语义下的自动填充 已配置的密码管理器

注意这条要求覆盖的是整条认证链路:即使主登录表单完全合规,如果 MFA 第二步只有一条"记住我 12 年前的安全答案"的路径,整条流程仍不满足规则。这也是技能文件中"评估完整认证路径,包括错误处理和备用方式"这一边界声明的落地含义。

最佳实践三:反滥用控制的相称性(proportionality)

原文档的表述是:如果在认证流程中使用 CAPTCHA 或其他滥用缓解手段,必须提供一条不强制记忆或誊写的替代路径。可访问性与防滥用不是相互竞争的目标,而是需要共同设计

仓库将这一交叉点显式编码在规则关联关系中:form-captcha.mdx 被列为本规则的相关规则,关联理由(引自 accessible-authentication.mdx 的 frontmatter)是"反滥用控制往往正是合规替代认证路径断裂的地方"。实操含义是:审查 CAPTCHA 组件时,除检查组件本身的可达性外,还要回答"如果用户无法通过该 CAPTCHA,是否存在另一条完成认证的合规路径?"

标准映射:WCAG 2.2 SC 3.3.8 与例外

本规则映射到 WCAG 2.2 Success Criterion 3.3.8 Accessible Authentication (Minimum)。原文档特别澄清了一个常见误解:

实际目标不是"更少的安全",而是至少一条不依赖认知功能测试的可行路径。

原文档给出三条例外边界(Exceptions),审查时不应误报:

  1. 重复输入新密码:当系统不会把用户刚输入的密码回显给其本人时,"确认密码"式的重新输入是有效的安全例外(SC 3.3.8 的 c 条款精神即"不能简单重做/重输新输入的内容");
  2. MFA 与本规则兼容,但用户仍需至少一条不依赖记忆或誊写的实用路径;
  3. 无障碍不要求移除安全控制,而是要求选择用户实际能完成的安全控制。

验证清单:自动化检查 + 手动检查

自动化检查(Automated Checks)

原文档给出的两条静态/自动化检查方向:

  • 在认证流程代码中搜索:阻止粘贴的事件处理器(onpaste="return false"paste 事件的 preventDefault())、自定义 OTP 拆分组件、缺失 autocomplete 属性的认证字段;
  • 校验 usernamecurrent-passwordnew-passwordone-time-code 四类字段是否使用了恰当的自动填充语义。

用 ripgrep 风格的模式表达,第一条检查可以落地为:

# 在认证相关目录中搜索阻止粘贴的处理器
rg -n "onpaste\s*=|'paste'|\\"paste\\"" auth/
# 搜索缺失 autocomplete 的认证输入
rg -n "type=\"(password|email|tel)\"" -g '!*.test.*' auth/

(以上为本仓库文档给出的检查思路的代码化表达,具体目录按项目结构调整。)

手动检查(Manual Checks)

原文档列出的四条人工验证步骤,构成一条完整的验收清单:

  1. 密码管理器测试签到——自动填充应命中用户名和密码两个字段;
  2. 粘贴一个 OTP,或在浏览器支持时让它自动填充——单输入框 + one-time-code 语义下这一步应当"零成本"完成;
  3. 演练恢复流程和 MFA 流程,而不只是主登录表单——这是最常被漏测的部分;
  4. 判定失败的判据:如果唯一可用路径要求用户记忆、誊写或解答认知测试,且不存在辅助替代路径,则检查不通过。

仓库中的配套工件与延伸阅读

围绕这条规则,仓库维护了三类配套工件,可用于持续工程化上述清单:

  • 技能(Skill)工件SKILL.md 定义了面向 Agent 的 Quick Reference / Check / Fix / Explain / Code Review 五段式工作流,把人工清单转化为可重复执行的审查提示;rule.md 则是其中"完整实现细节、代码示例与框架级指导"的引用文件,即本文的主体来源;
  • 规则源文档(Source of Truth)accessible-authentication.mdx 包含规则的完整元数据、资料来源(sources)与相关规则图(relatedRules),是规则站点化与工具化消费的入口;
  • 关联规则paste-inputs.mdxpassword-field-security.mdxform-captcha.mdxsession-timeout-recovery.mdx 分别覆盖粘贴权限、密码字段安全、CAPTCHA 相称性与会话恢复,四者与本篇规则共同构成认证流程的完整可访问性审查面。

小结:无障碍认证的工程化落点可以压缩为四件事——为每个认证字段写对 autocomplete 语义、保持 OTP 单输入框可粘贴可自动填充、在登录/MFA/恢复链路上各保留一条 Passkey 或 magic link 式的非记忆路径、把 CAPTCHA 的替代路径纳入与主流程同等强度的验证。满足这四点后,流程在 WCAG 2.2 SC 3.3.8 意义上的合规性与在真实用户群体的完成率应当同步提升——这正是原文档"无障碍与防滥用共同设计"论断的实践含义。

登录后查看全文
热门项目推荐
相关项目推荐