You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Credential Management API存储密码异常:get方法返回null

问题

我希望使用Credential Management API为用户存储密码。在本地服务器运行以下代码时,get方法返回null:

await (async function testStoredPassword({id, origin, password, iconURL, name}) {
  const opts = {id, origin, password, iconURL, name};
  const credential = await navigator.credentials.create({password: opts});
  if (credential === null) {
    return;
  }
  console.log({credential});
  await navigator.credentials.store(credential);
  const roundTripCredential = await navigator.credentials.get({
    password: true,
    mediation: 'optional',
  });
  console.log({roundTripCredential});
  return roundTripCredential;
})({
  id: "id1",
  origin: location.origin,
  password: "password1",
  iconURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Flat_tick_icon.svg/240px-Flat_tick_icon.svg.png",
  name: "name1"
});

控制台输出:

{credential: PasswordCredential}
{roundTripCredential: null}

我原以为是实现存在问题,或是localhost环境导致(但查阅资料得知此环境应支持),但在线演示也出现同样问题。查阅相关规范及技术博客后,理论上该代码应正常运行。我的运行环境为Windows 11和Chrome 120。

解决方案

核心原因:Chrome的安全与自动填充策略限制

Chrome对Credential Management API的调用有严格的触发条件,尤其是get()方法,不会直接返回刚存储的凭证,核心限制点在于必须由用户主动交互触发API调用,且浏览器内部存储存在异步延迟。

具体修复步骤:

  1. 绑定API调用到用户交互事件
    所有涉及credentials.create()、store()、get()的逻辑必须绑定到用户主动触发的事件(比如按钮点击),否则Chrome会出于安全策略拦截并返回null。

    修改后的代码示例:

    // 页面添加按钮
    document.body.innerHTML += '<button id="save-cred">保存凭证</button><button id="get-cred">获取凭证</button>';
    
    // 保存凭证逻辑
    document.getElementById('save-cred').addEventListener('click', async () => {
      const credential = await navigator.credentials.create({
        password: {
          id: "id1",
          origin: location.origin,
          password: "password1",
          iconURL: "https://upload.wikimedia.org/wikipedia/commons/thumb/7/73/Flat_tick_icon.svg/240px-Flat_tick_icon.svg.png",
          name: "name1"
        }
      });
      await navigator.credentials.store(credential);
      console.log('凭证已存储');
    });
    
    // 获取凭证逻辑
    document.getElementById('get-cred').addEventListener('click', async () => {
      const roundTripCredential = await navigator.credentials.get({
        password: true,
        mediation: 'optional',
      });
      console.log({roundTripCredential});
    });
    
  2. 检查浏览器自动填充设置

    • 确认Chrome已开启「自动填充密码」功能(路径:设置 > 隐私和安全 > 自动填充 > 密码管理器)
    • 确保当前站点未被加入「从不保存密码」列表
  3. 拆分存储与获取的交互流程
    避免在同一用户交互中连续调用store()和get(),浏览器内部存储凭证存在异步延迟,分开触发能确保获取到已持久化的凭证。

  4. 验证origin参数匹配性
    确保origin参数严格匹配当前页面的源(协议+域名+端口),使用location.origin即可自动获取正确值,无需手动拼接。


内容的提问来源于stack exchange,提问作者Yuval

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.04 05:02:26