如需让用户登录,请从浏览器的密码管理工具中检索凭据,并使用这些凭据自动登录用户。对于拥有多个账号的用户,让他们使用账号选择器,只需点按一下即可选择账号。
自动登录
自动登录可能发生在您网站上的任何位置,不仅是首页,还包括其他叶级页。当用户通过搜索引擎访问您网站中的各个网页时,此功能非常有用。
如需启用自动登录,请执行以下操作:
- 获取凭证信息。
- 对用户进行身份验证。
- 更新界面或前往个性化页面。
获取凭证信息
如需获取凭据信息,请调用 navigator.credentials.get()。通过提供 password 或 federated 来指定要请求的凭据类型。
始终使用 mediation: 'silent' 进行自动登录,以便在用户执行以下操作时轻松关闭该流程:
- 未存储任何凭证。
- 存储了多个凭证。
- 已退出账号。
在获取凭证之前,请务必检查用户是否已登录:
if (window.PasswordCredential || window.FederatedCredential) {
if (!user.isSignedIn()) {
navigator.credentials.get({
password: true,
federated: {
providers: ['https://accounts.google.com'],
},
mediation: 'silent',
});
// ...
}
}
navigator.credentials.get() 返回的 promise 会解析为凭据对象或 null。如需确定它是 PasswordCredential 还是 FederatedCredential,只需查看对象的 .type 属性,该属性将为 password 或 federated。
如果 .type 为 federated,则 .provider 属性是表示身份提供方的字符串。
对用户进行身份验证
获得凭证后,根据凭证类型(password 或 federated)运行身份验证流程:
}).then(c => {
if (c) {
switch (c.type) {
case 'password':
return sendRequest(c);
break;
case 'federated':
return gSignIn(c);
break;
}
} else {
return Promise.resolve();
}
当 promise 解析后,检查您是否收到了凭证对象。 否则,则表示无法自动登录。 静默关闭自动登录流程。
更新界面
如果身份验证成功,请更新界面或将用户转到个性化页面:
}).then(profile => {
if (profile) {
updateUI(profile);
}
别忘了显示身份验证出错提示
为避免用户感到困惑,用户应在获取凭据对象时看到一条蓝色消息框,其中显示“正在登录”:
一个重要提示:如果您成功获取了凭据对象,但未能对用户进行身份验证,则应显示一条出错提示:
}).catch(error => {
showError('Sign-in Failed');
});
}
}
完整代码示例
if (window.PasswordCredential || window.FederatedCredential) {
if (!user.isSignedIn()) {
navigator.credentials
.get({
password: true,
federated: {
providers: ['https://accounts.google.com'],
},
mediation: 'silent',
})
.then((c) => {
if (c) {
switch (c.type) {
case 'password':
return sendRequest(c);
break;
case 'federated':
return gSignIn(c);
break;
}
} else {
return Promise.resolve();
}
})
.then((profile) => {
if (profile) {
updateUI(profile);
}
})
.catch((error) => {
showError('Sign-in Failed');
});
}
}
通过账号选择器登录
如果用户需要中介或拥有多个账号,请使用账号选择器让用户登录,跳过普通登录表单,例如:
通过账号选择器登录的步骤与自动登录相同,只是在获取凭据信息时需要额外调用一次以显示账号选择器:
- 获取凭据信息并显示账号选择器。
- 对用户进行身份验证。
- 更新界面或前往个性化页面。
获取凭证信息并显示账号选择器
在响应定义的用户操作(例如,用户点按“登录”按钮)时显示账号选择器。调用 navigator.credentials.get(),并添加 mediation: 'optional' 或 mediation: 'required' 以显示账号选择器。
当 mediation 为 required 时,系统始终会向用户显示账号选择器以供登录。此选项可让拥有多个账号的用户轻松切换账号。
当 mediation 为 optional 时,系统会在 navigator.credentials.preventSilentAccess() 调用后明确向用户显示账号选择器,以便用户登录。这通常是为了确保在用户选择退出账号或取消注册后不会自动登录。
显示 mediation: 'optional' 的示例:
var signin = document.querySelector('#signin');
signin.addEventListener('click', e => {
if (window.PasswordCredential || window.FederatedCredential) {
navigator.credentials.get({
password: true,
federated: {
providers: [
'https://accounts.google.com'
]
},
mediation: 'optional'
}).then(c => {
用户选择账号后,Promise 会使用凭据进行解析。
如果用户取消账号选择器,或者没有存储任何凭据,则 promise 会解析为 null。
在这种情况下,请回退到登录表单体验。
别忘了回退到登录表单
如果出现以下任一情况,您应回退到登录表单:
- 系统不会存储任何凭证。
- 用户关闭了账号选择器,未选择任何账号。
- 此 API 不可用。
}).then(profile => {
if (profile) {
updateUI(profile);
} else {
location.href = '/signin';
}
}).catch(error => {
location.href = '/signin';
});
完整代码示例
var signin = document.querySelector('#signin');
signin.addEventListener('click', (e) => {
if (window.PasswordCredential || window.FederatedCredential) {
navigator.credentials
.get({
password: true,
federated: {
providers: ['https://accounts.google.com'],
},
mediation: 'optional',
})
.then((c) => {
if (c) {
switch (c.type) {
case 'password':
return sendRequest(c);
break;
case 'federated':
return gSignIn(c);
break;
}
} else {
return Promise.resolve();
}
})
.then((profile) => {
if (profile) {
updateUI(profile);
} else {
location.href = '/signin';
}
})
.catch((error) => {
location.href = '/signin';
});
}
});
联合登录
联合登录让用户只需点按一下即可登录,而无需记住您网站的其他登录详细信息。
如需实现联合登录,请执行以下操作:
- 使用第三方身份验证用户。
- 存储身份信息。
- 更新界面或进入个性化页面(与自动登录相同)。
使用第三方身份验证用户
当用户点按联合登录按钮时,使用 FederatedCredential 运行特定的身份提供方身份验证流程。
例如,如果提供方是 Google,请使用 Google 登录 JavaScript 库:
navigator.credentials
.get({
password: true,
mediation: 'optional',
federated: {
providers: ['https://account.google.com'],
},
})
.then(function (cred) {
if (cred) {
// Instantiate an auth object
var auth2 = gapi.auth2.getAuthInstance();
// Is this user already signed in?
if (auth2.isSignedIn.get()) {
var googleUser = auth2.currentUser.get();
// Same user as in the credential object?
if (googleUser.getBasicProfile().getEmail() === cred.id) {
// Continue with the signed-in user.
return Promise.resolve(googleUser);
}
}
// Otherwise, run a new authentication flow.
return auth2.signIn({
login_hint: id || '',
});
}
});
Google 登录会生成一个 ID 令牌作为身份验证证明。
一般来说,联合登录是基于 OpenID Connect 或 OAuth 等标准协议构建的。如需了解如何使用联合账号进行身份验证,请参阅相应联合身份提供方的文档。热门示例包括:
存储身份信息
身份验证完成后,您可以存储身份信息。
您将在此处存储的信息是来自身份提供方的 id 以及表示身份提供方的提供方字符串(name 和 iconURL 是可选的)。如需详细了解此信息,请参阅凭证管理规范。
如需存储联合账号详细信息,请使用用户标识符和提供商标识符实例化一个新的 FederatedCredential 对象。然后调用 navigator.credentials.store() 来存储身份信息。
成功联合后,同步或异步实例化 FederatedCredential:
同步方法示例:
// Create credential object synchronously.
var cred = new FederatedCredential({
id: id, // id in IdP
provider: 'https://account.google.com', // A string representing IdP
name: name, // name in IdP
iconURL: iconUrl, // Profile image url
});
异步方法示例:
// Create credential object asynchronously.
var cred = await navigator.credentials.create({
federated: {
id: id,
provider: 'https://accounts.google.com',
name: name,
iconURL: iconUrl,
},
});
然后存储凭证对象:
// Store it
navigator.credentials.store(cred).then(function () {
// continuation
});
退出账号
在用户点按退出登录按钮时,让用户退出登录。 请先终止会话,然后为日后的访问关闭自动登录功能。 (如何终止会话完全由您决定。)
为日后的访问关闭自动登录功能
致电navigator.credentials.preventSilentAccess():
signoutUser();
if (navigator.credentials && navigator.credentials.preventSilentAccess) {
navigator.credentials.preventSilentAccess();
}
这样可以确保在用户下次启用自动登录之前,系统不会自动登录。 如需恢复自动登录,用户可以选择从账号选择器中选择要登录的账号,从而有意登录。然后,用户会始终保持登录状态,直到他们明确退出账号。