本文介紹的部分更新會在 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
顯示,供使用者選擇:
![帳戶選擇工具顯示所選子網域的登入詳細資料](https://developer.chrome.google.cn/static/blog/credential-management-updates/image/account-chooser-showing-s-369ff3f4bb61e.png?authuser=19&hl=zh-tw)
Chrome 60 版
Chrome 60 推出了幾項重要的變更 Credential Management API:
由於自訂
fetch()
函式不再需要擷取密碼, 並且將於近期淘汰。navigator.credentials.get()
現在接受mediation
列舉 而不是布林值標記unmediated
。新方法
navigator.credentials.create()
以非同步方式建立憑證物件
需要處理特徵偵測功能
確認 Credential Management API 用於存取密碼和
可使用聯合憑證,檢查 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 物件中傳送密碼。
他們必須將密碼的雜湊值傳送到伺服器。
執行安全性分析並識別隱藏密碼後 的 JavaScript 無法像我們所期望的一樣有效阻止所有攻擊媒介 我們決定做出改變
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?我們提供了遷移指南文件 即可按照指示升級至新版本