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
之后。
在下面的屏幕截图中,存储在 login.aliexpress.com
下的凭据信息
对 m.aliexpress.com
可见,并可供用户选择:
Chrome 60
Chrome 60 针对 Credential Management API:
由于提取密码不再需要自定义
fetch()
函数, 它很快就会被弃用。navigator.credentials.get()
现在接受枚举mediation
而不是布尔标志unmediated
。新方法
navigator.credentials.create()
异步创建凭据对象。
特征检测需要注意
查看用于访问基于密码和
联合凭据是否可用,请检查 window.PasswordCredential
或
window.FederatedCredential
可用。
if (window.PasswordCredential || window.FederatedCredential) {
// The Credential Management API is available
}
PasswordCredential
对象现在包含密码
Credential Management API 采用保守的方法处理密码。
它从 JavaScript 中隐藏密码,这需要开发者
将 PasswordCredential
对象直接发送到其服务器
,通过 fetch()
API 的扩展进行验证。
但是,这种方法带来了许多限制。 我们已收到反馈,指出开发者无法使用该 API,原因如下:
他们必须将密码作为 JSON 对象的一部分进行发送。
他们必须将密码的哈希值发送至服务器。
在执行安全分析并确定隐藏密码后 无法像我们希望的那样有效地阻止所有攻击途径, 我们已决定进行相关更改
Credential Management API 现在包含原始密码 存储在返回的凭据对象中,以便您能以纯文本形式访问它。 您可以使用现有方法将凭据信息传送到服务器:
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
mediation: 'silent'
}).then(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
。
navigator.credentials.get()
现在接受枚举中介
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'
}).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?我们提供了迁移指南文档 请遵循以下步骤来升级到新版本。