登录用户

Meggin Kearney
Meggin Kearney

如需让用户登录,请从浏览器的密码管理器检索凭据,并使用这些凭据自动让用户登录。对于拥有多个账号的用户,让他们只需点按一下账号选择器即可选择账号。

自动登录可以发生在您网站上的任何位置,不仅仅是顶级页面,还包括其他叶级页面。当用户通过搜索引擎访问您网站中的各个网页时,此维度非常有用。

如需启用自动登录功能,请执行以下操作:

  1. 获取凭据信息。
  2. 对用户进行身份验证。
  3. 更新界面或前往个性化页面。

获取凭据信息

浏览器支持

  • Chrome:51.
  • Edge:18.
  • Firefox:60.
  • Safari:13.

来源

如需获取凭据信息,请调用 navigator.credentials.get()。通过为其提供 passwordfederated,指定要请求的凭据类型。

请始终使用 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 属性,即 passwordfederated

如果 .typefederated,则 .provider 属性是一个表示身份提供方的字符串。

对用户进行身份验证

获取凭据后,请根据凭据类型(passwordfederated)运行身份验证流程:

    }).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');
     
});
 
}
}

通过账号选择器登录

如果用户需要调节,或具有多个账号,则使用账号选择器让用户登录,从而跳过普通的登录表单,例如:

显示多个账号的 Google 账号选择器。

通过账号选择器登录的步骤与自动登录相同,只不过在获取凭据信息时,需要额外调用一个用于显示账号选择器的函数:

  1. 获取凭据信息并显示账号选择器。
  2. 对用户进行身份验证
  3. 更新界面或前往个性化页面

获取凭据信息并显示账号选择器

在用户执行定义的操作(例如点按“登录”按钮)时显示账号选择器。调用 navigator.credentials.get(),然后添加 mediation: 'optional'mediation: 'required' 以显示账号选择器。

mediationrequired 时,系统始终会向用户显示用于登录的账号选择器。借助此选项,拥有多个账号的用户可以轻松在这些账号之间切换。 当 mediationoptional 时,系统会在 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';
     
});
 
}
});

联合登录

借助联合登录,用户只需点按一下即可登录,而无需记住您网站的其他登录详细信息。

如需实现联合登录,请执行以下操作:

  1. 使用第三方身份验证用户身份。
  2. 存储身份信息。
  3. 更新界面或前往个性化页面(与自动登录相同)。

使用第三方身份对用户进行身份验证

当用户点按联合登录按钮时,使用 FederatedCredential 运行特定身份提供程序身份验证流程。

浏览器支持

  • Chrome:51.
  • Edge:79。
  • Firefox:不受支持。
  • Safari:不受支持。

来源

例如,如果提供程序为 Google,请使用 Google Sign-In 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 Sign-In 会生成一个 ID 令牌作为身份验证的证明。

通常,联合登录是基于 OpenID ConnectOAuth 等标准协议构建的。如需了解如何使用联合账号进行身份验证,请参阅相应联合身份提供方的文档。常见示例包括:

存储身份信息

身份验证完成后,您可以存储身份信息。您将在此处存储的信息是身份提供方的 id 以及表示身份提供方的提供方字符串(nameiconURL 是可选的)。如需详细了解此信息,请参阅凭据管理规范

如需存储联合账号详情,请使用用户标识符和提供程序标识符实例化一个新的 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();
}

这样可确保在用户下次启用自动登录功能之前,系统不会自动登录。 如需继续使用自动登录,用户可以选择主动登录,只需从账号选择器中选择他们在登录时要使用的账号。然后,用户在明确退出前始终可以重新登录。

反馈