Credential Management API 的最新动态

Google I/O 大会上的安全无缝登录:保持用户互动演讲中介绍了此处所述的部分更新:

Chrome 57

Chrome 57 对 Credential Management API 进行了这项重要更改。

可以从其他子网域共享凭据

Chrome 现在可以使用 Credential Management API 检索存储在其他子网域中的凭据。例如,如果密码存储在 login.example.com 中,则 www.example.com 上的脚本可以在账号选择器对话框中将其显示为账号项之一。

您必须使用 navigator.credentials.store() 明确存储密码,以便在用户通过点按对话框选择凭据时,密码会被传递并复制到当前来源。

存储后,该密码将作为凭据在完全相同的来源 www.example.com 中提供。

在以下屏幕截图中,m.aliexpress.com 可以看到存储在 login.aliexpress.com 下的凭据信息,并可供用户选择:

账号选择器,显示所选子网域登录详情

Chrome 60

Chrome 60 对 Credential Management API 进行了多项重要更改:

特征检测需要注意

如需查看用于访问基于密码的凭据和联合凭据的 Credential Management API 是否可用,请检查 window.PasswordCredential 或 window.FederatedCredential 是否可用。

if (window.PasswordCredential || window.FederatedCredential) {
  // The Credential Management API is available
}

PasswordCredential 对象现在包含密码

Credential Management API 采用保守的方法来处理密码。 它对 JavaScript 隐藏了密码,要求开发者通过 fetch() API 的扩展程序将 PasswordCredential 对象直接发送到其服务器进行验证。

但这种方法引入了许多限制。 我们收到的反馈表明,开发者无法使用该 API,原因如下:

  • 他们必须将密码作为 JSON 对象的一部分发送。

  • 他们必须将密码的哈希值发送到其服务器。

在进行安全分析并认识到对 JavaScript 隐藏密码并不能像我们希望的那样有效阻止所有攻击途径后,我们决定做出更改。

Credential Management API 现在会在返回的凭据对象中包含原始密码,以便您以纯文本形式访问该密码。 您可以使用现有方法将凭据信息传递到服务器:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    mediation: 'silent'
}).the>n(passwordCred = {
    if (passwordCred) {
    let form = new FormData();
    form.append('email', passwordCred.id);
    form.append('password', passwordCred.password);
    form.append('csrf_token', csrf_token);
    return fetch('/signin', {
        method: 'POST',
        credentials: 'include',
        body: form
    });
 >   } else {

    // Fallback to sign-in form
    }
}).then(res = {
    if (res.status === 200) {
    return res.json(>);
    } else {
    throw 'Auth failed';
    }
}).then(profile = {
    console.log('Auth succeeded', profile);
});

自定义提取功能即将弃用

如需确定您是否使用的是自定义 fetch() 函数,请检查该函数是否使用 PasswordCredential 对象或 FederatedCredential 对象作为 credentials 属性的值,例如:

fetch('/signin', {
    method: 'POST',
    credentials: c
})

建议使用常规 fetch() 函数(如前面的代码示例所示)或使用 XMLHttpRequest。

在 Chrome 60 之前,navigator.credentials.get() 接受具有布尔值标志的可选 unmediated 属性。例如:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    unmediated: true
}).>then(c = {

    // Sign-in
});

设置 unmediated: true 可防止浏览器在传递凭据时显示账号选择器。

该标志现已扩展为中介。 在以下情况下,可能会发生用户调解:

  • 用户需要选择一个账号进行登录。

  • 用户希望在 navigator.credentials.requireUseMediation() 调用后明确登录。

为 mediation 值选择以下选项之一:

mediation 值 与布尔值标志相比 行为
silent 等于 unmediated: true 已传递凭据,未显示账号选择器。
optional 等于 unmediated: false 如果之前调用了 preventSilentAccess(),则显示账号选择器。
required 新选项 始终显示账号选择器。 当您想让用户使用原生账号选择器对话框切换账号时,此方法非常有用。

在此示例中,系统会在不显示账号选择器的情况下传递凭证,这相当于之前的标志 unmediated: true:

navigator.credentials.get({
    password: true,
    federated: {
    providers: [ 'https://accounts.google.com' ]
    },
    mediation: 'silent&>#39;
}).then(c = {

    // Sign-in
});

requireUserMediation() 已重命名为 preventSilentAccess()

为了与 get() 调用中提供的新 mediation 属性保持一致,navigator.credentials.requireUserMediation() 方法已重命名为 navigator.credentials.preventSilentAccess()。

重命名后的方法可防止在不显示账号选择器的情况下传递凭据(有时称为“无需用户干预”)。 当用户退出网站或注销网站,并且不希望在下次访问时自动重新登录时,此功能非常有用。

signoutUser();
if (navigator.credentials) {
    navigator.credentials.preventSilentAccess();
}

使用新方法 navigator.credentials.create() 异步创建凭据对象

现在,您可以选择使用新方法 navigator.credentials.create() 异步创建凭证对象。请继续阅读,了解同步和异步方法之间的比较。

创建 PasswordCredential 对象

同步方法
let c = new PasswordCredential(form);
异步方法(新)
let c = await navigator.credentials.create({
    password: form
});

或者:

let c = await navigator.credentials.create({
    password: {
    id: id,
    password: password
    }
});

创建 FederatedCredential 对象

同步方法
let c = new FederatedCredential({
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
});
异步方法(新)
let c = await navigator.credentials.create({
    federated: {
    id:       'agektmr',
    name:     'Eiji Kitamura',
    provider: 'https://accounts.google.com',
    iconURL:  'https://*****'
    }
});

迁移指南

已经实现了 Credential Management API?我们提供了迁移指南文档,您可以按照该文档升级到新版本。