[譯] 使用認證管理 API 簡化登陸

原文鏈接:http://lea.verou.me/2015/12/my-positive-experience-as-a-woman-in-tech/javascript

爲了提供優質的用戶體驗,咱們應該幫助用戶在不一樣網頁進行身份認證。完成認證的用戶能夠在不一樣網頁擁有不一樣的資料,在多設備之間同步數據,或是在離線狀況下處理數據;能夠擴展的功能數之不盡。可是建立帳號、記住和輸入密碼對用戶來講很是麻煩,尤爲是在手機端,這一般致使用戶在不一樣網站使用同一份密碼。這在安全性上有很大的風險。html

Chrome 51(最新版本)支持了Credential Management API(證書管理API)。它遵循了W3C提議的標準,爲開發者提供了管理瀏覽器認證的入口,以幫助用戶以更簡單的方式登陸。java

認證管理API的設計目標

經過認證管理API, 開發者能夠保存和獲取密碼認證信息和聯合認證信息。它提供了一下3個方法:android

  • navigator.credentials.get()git

  • navigator.credentials.store()github

  • navigator.credentials.requireUserMediation()web

經過使用這些API,開發者能夠完成如下強大的功能:api

  • 讓用戶能夠經過一次點擊完成登陸數組

  • 記錄用戶登陸時使用的聯合認證帳號瀏覽器

  • 當session過時時,幫助用戶從新登陸

在Chrome的實現中,認證信息會被保存在Chrome的密碼管理器中。用戶登錄後,能夠在多設備之間同步密碼。同步的密碼也能夠被分享給Android應用,只要這些應用集成了Smart Lock for Passwords for Android以提供無縫的跨平臺體驗.

在網站中集成認證管理API

如何使用認證管理API,取決於你的網站架構是如何設計的。你的網站是一個單頁應用?是一個涉及頁面切換的傳統架構?只能在首頁登陸?仍是處處都能登陸?用戶能否在不登陸的狀況下瀏覽網頁?登陸操做是否在彈出的窗口中進行?仍是說須要操做不一樣的頁面才能登陸。

咱們不可能覆蓋全部的場景,但讓咱們先經過一個典型的單頁應用瞭解一下:

  • 首頁是一個登陸表單。

  • 點擊「登陸」按鈕時,用戶會被導向一個登陸表單。

  • 註冊和登陸表單都提供了id/password認證與聯合認證登陸的選項,例如:經過Google登陸,或經過Facebook登陸。

使用認證管理API,咱們能夠爲網站添加如下功能,例如:

  • 在用戶登陸時,顯示帳號選擇框: 當用戶點擊「登陸」時,彈出原生帳號選擇框。

  • 保存認證信息: 在用戶成功登陸後,使用瀏覽器的密碼管理器保存認證信息,以便往後使用。

  • 調解自動登陸: 一旦用戶退出登陸,在用戶下一次訪問時,中止自動登陸。

大家能夠經過這個例子體驗一下,它的代碼在這兒.

注意:這些API只能在安全網站中使用,例如HTTPS網站、locolhost

登陸時顯示帳號選擇框

在用戶點擊了「登陸」按鈕,並跳到登陸表單以前,你能夠經過navigator.credentials.get()方法得到認證信息。Chrome會彈出一個帳號選擇框,供用戶選擇。


彈出了一個帳號選擇框,用戶可選擇一個帳號進行登陸。

獲取密碼認證對象

若是想支持經過密碼認證登陸,請使用password: true

navigator.credentials.get({  
  password: true, // 設置爲true,以獲取密碼認證對象
}).then(function(cred) {  
  // 繼續
  ...
使用密碼認證登陸

當用戶選擇了一個帳號時,resolve函數會收到一個密碼認證對象,你能夠經過fetch()方法將信息發送到服務器。

// 延續上一個例子
}).then(function(cred) {  
  if (cred) {  
    if (cred.type == 'password') {  
      // 構建FormData對象
      var form = new FormData();

      // 添加CSRF令牌
      var csrf_token = document.querySelector('csrf_token').value;  
      form.append('csrf_token', csrf_token);

      // 你能夠將額外信息添加到`.additionalData`
      cred.additionalData = form;

      // 將認證對象做爲`credentials`經過`POST`請求發送
      // id, 密碼和額外信息會被加密,並做爲HTTP主體被髮送給接口
      fetch(url, {           // 請保證url是HTTPS連接
        method: 'POST',      // 使用POST方法
        credentials: cred    // 添加密碼認證對象
      }).then(function() {  
        // 繼續  
      });  
    } else if (cred.type == 'federated') {  
      // 繼續
使用聯合認證登陸

若是想爲用戶展現聯合登陸帳號,請在調用get()方法時,經過federated選項定義一個包含帳號提供者id的數組。


密碼管理器保存了多個帳號

navigator.credentials.get({  
  password: true, // 設置爲true,以得到密碼認證對象
  federated: {  
    providers: [  // 定義一個由聯合帳號供應者id組成的數組
      'https://accounts.google.com',  
      'https://www.facebook.com'  
    ]  
  }  
}).then(function(cred) {  
  // continuation  
  ...

經過認證對象的type屬性,能夠檢查它的類型是PasswordCredential(type == 'password')仍是FederatedCredential(type == 'federated')。
若是是FederatedCredential,你能夠將它包含的信息發送給對應的API。

});  
    } else if (cred.type == 'federated') {  
      // `provider`屬性包含了聯合帳號供應者的id
      switch (cred.provider) {  
        case 'https://accounts.google.com':  
          // 使用Google Sign-In進行聯合登陸
          var auth2 = gapi.auth2.getAuthInstance();

          // 使用Google Sign-In庫時,能夠經過login_hint指定一個帳號
          return auth2.signIn({  
            login_hint: cred.id || ''  
          }).then(function(profile) {  
            // 繼續  
          });  
          break;

        case 'https://www.facebook.com':  
          // 使用Facebook Login進行聯合登陸
          // 繼續
          break;

        default:  
          // 顯示錶單
          break;  
      }  
    }  
  // 若是cred是undefined
  } else {  
      // 顯示錶單

保存認證對象

當用戶經過表單登陸你的網站時,你可使用navigator.credentials.store()來保存認證信息。瀏覽器會詢問用戶是否但願保存。你能夠根據認證的類型,決定使用new PasswordCredential()仍是new FederatedCredential()來建立認證對象並保存。


Chrome詢問用戶是否但願保存認證信息(或是做爲聯合帳號)

經過表單元素建立和保存密碼認證對象

如下代碼經過屬性autocomplete,自動將表單元素 映射PasswordCredential對象的參數。

HTML

<form id="form" method="post">
  <input type="text" name="id" autocomplete="username" />  
  <input type="password" name="password" autocomplete="current-password" />  
  <input type="hidden" name="csrf_token" value="******" />
</form>

JavaScript:

var form = document.querySelector('\#form');  
var cred = new PasswordCredential(form);  
// 保存認證對象
navigator.credentials.store(cred)  
.then(function() {  
  // 繼續
});
建立和保存聯合認證對象
// 在聯合認證後,經過你得到的信息建立一個FederatedCredential對象
var cred = new FederatedCredential({  
  id: id,                                  // 用戶id
  name: name,                              // 可選的用戶名
  provider: 'https://accounts.google.com',  // 聯合帳號提供者的id
  iconURL: iconUrl                         // 可選的用戶頭像地址
});  
// 保存認證對象
navigator.credentials.store(cred)  
.then(function() {  
  // 繼續
});

使用戶自動從新登陸

當用戶再次訪問網站時,session有可能已經失效了。咱們沒必要麻煩用戶每次回訪的時候從新輸入密碼。能夠幫助他們自動從新登陸。


當用戶自動登陸時,會彈出一個通知

獲取一個認證對象
navigator.credentials.get({  
  password: true,
  federated: {
    providers: [
      'https://accounts.google.com',  
      'https://www.facebook.com'  
    ]  
  },  
  unmediated: true // 設置爲true,以支持用戶自動登陸  
}).then(function(cred) {  
  if (cred) {  
    // 能夠自動登陸
    ...  
  } else {  
    // 不能夠自動登陸
    ...
  }  
});

這段代碼與你在前面的「顯示帳號選擇框」部分的代碼類似。惟一的區別是這兒設置了unmediated: true

這會使函數立刻resolve,並返回一個認證對象,幫助用戶自動登陸。自動登陸有如下條件:

  • 瀏覽器已顯式地告知用戶正在進行自動登陸

  • 用戶曾經經過認證管理API登錄了網站

  • 用戶在瀏覽你的網站時只保存了一個認證對象

  • 用戶在上一次訪問時沒有主動退出登陸

若是任意條件不符合,這個函數便會被reject

調解(Mediate)自動登陸

當用戶退出登陸時,應該由你來確保用戶下次回訪時不會自動登陸 。認證管理API提供了一種叫做mediation(調解)的機制來確保這一點。你能夠經過調用navigator.credentials.requireUserMediation()來開啓調解模式。只要用戶在這個網站中的調解狀態爲開啓,那麼若是你在navigator.credentials.get()方法中選擇了unmediate:true,這個函數會在resolve時,傳入undefined

調解自動登陸
navigator.credentials.requireUserMediation();

FAQ

在網頁中,Javascript是否有可能得到原始密碼?

不能。密碼只能做爲PasswordCredential對象中的一部分,對外是不可訪問的。
No. You can only obtain passwords as a part of PasswordCredential and it’s not exposable by any means.

Is it possible to store 3 set of digits for an id using Credential Management API?
咱們能夠經過認證管理API爲一個id保存三組數字嗎?

目前還不行。咱們很是感謝你對標準的反饋 

我能夠在iframe中使用認證管理API嗎?

這個API只能在最高級的上下文中使用。若是在iframe中調用.get().store()方法,這些方法會立刻resolve,而且不會產生任何效果。

我能夠在個人密碼管理Chrome擴展中集成認證管理API嗎?

你能夠重寫navigator.credentials,並將它指向你的Chrome擴展,由擴展來get()store()認證對象。

做者

Profile photo of Eiji Kitamura

相關文章
相關標籤/搜索