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调用,且浏览器内部存储存在异步延迟。
具体修复步骤:
绑定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}); });检查浏览器自动填充设置
- 确认Chrome已开启「自动填充密码」功能(路径:设置 > 隐私和安全 > 自动填充 > 密码管理器)
- 确保当前站点未被加入「从不保存密码」列表
拆分存储与获取的交互流程
避免在同一用户交互中连续调用store()和get(),浏览器内部存储凭证存在异步延迟,分开触发能确保获取到已持久化的凭证。验证origin参数匹配性
确保origin参数严格匹配当前页面的源(协议+域名+端口),使用location.origin即可自动获取正确值,无需手动拼接。
内容的提问来源于stack exchange,提问作者Yuval
相关产品推荐
相关产品推荐

