請盡可能簡化註冊和登入表單。
儲存登入表單中的憑證 如此一來,使用者下次返回時就不必再次登入。
如何儲存表單的使用者憑證:
- 在表單中加入
autocomplete
。 - 禁止提交表單。
- 傳送要求以進行驗證。
- 儲存憑證。
- 更新使用者介面或前往個人化頁面。
在表單中加入 autocomplete
繼續編輯前
檢查表單是否包含 autocomplete
屬性。
這有助於 Credential Management API 找到 id
和 password
然後建構憑證物件
這也有助於瀏覽器不支援 Credential Management API 瞭解語意 進一步瞭解自動填入功能: 這篇文章, Jason Grigsby。
<form id="signup" method="post">
<input name="email" type="text" autocomplete="username email" />
<input name="display-name" type="text" autocomplete="name" />
<input name="password" type="password" autocomplete="new-password" />
<input type="submit" value="Sign Up!" />
</form>
禁止提交表單
當使用者按下提交按鈕時,阻止系統提交表單,否則 會造成頁面轉換:
var f = document.querySelector('#signup');
f.addEventListener('submit', e => {
e.preventDefault();
只要防止頁面轉換 您可以在驗證憑證的真實性時保留憑證資訊。
傳送要求進行驗證
如要驗證使用者,請使用 AJAX 將憑證資訊傳送至您的伺服器。
在伺服器端建立端點 (或直接修改現有端點) 會以 HTTP 代碼 200 或 401 回應,讓瀏覽器清楚顯示 註冊/登入/變更密碼是否成功。
例如:
// Try sign-in with AJAX
fetch('/signin', {
method: 'POST',
body: new FormData(e.target),
credentials: 'include',
});
儲存憑證
如要儲存憑證,請先檢查 API 是否可用。
接著將
PasswordCredential
敬上
做為引數
可以同步或非同步
致電
navigator.credentials.store()
。
如果 API 無法使用
只需將商家檔案資訊轉至下一個步驟即可。
同步範例:
if (window.PasswordCredential) {
var c = new PasswordCredential(e.target);
return navigator.credentials.store(c);
} else {
return Promise.resolve(profile);
}
非同步範例:
if (window.PasswordCredential) {
var c = await navigator.credentials.create({password: e.target});
return navigator.credentials.store(c);
} else {
return Promise.resolve(profile);
}
要求成功後,請儲存憑證資訊。 (如果要求失敗,請勿儲存憑證資訊 否則回訪者會感到困惑)。
Chrome 瀏覽器取得憑證資訊後 畫面上會彈出通知視窗,要求儲存憑證 或聯盟供應商的服務或產品。
![儲存憑證](https://web.dev/static/articles/security-credential-management-save-forms/image/store-credential-f27fdeafeab5c.png?authuser=6&hl=zh-tw)
更新 UI
如果一切順利,請使用設定檔資訊更新使用者介面 或前往個人化頁面
}).then(profile => {
if (profile) {
updateUI(profile);
}
}).catch(error => {
showError('Sign-in Failed');
});
});
完整程式碼範例
// Get form's DOM object
var f = document.querySelector('#signup');
f.addEventListener('submit', (e) => {
// Stop submitting form by itself
e.preventDefault();
// Try sign-in with AJAX
fetch('/signin', {
method: 'POST',
body: new FormData(e.target),
credentials: 'include',
})
.then((res) => {
if (res.status == 200) {
return Promise.resolve();
} else {
return Promise.reject('Sign-in failed');
}
})
.then((profile) => {
// Instantiate PasswordCredential with the form
if (window.PasswordCredential) {
var c = new PasswordCredential(e.target);
return navigator.credentials.store(c);
} else {
return Promise.resolve(profile);
}
})
.then((profile) => {
// Successful sign-in
if (profile) {
updateUI(profile);
}
})
.catch((error) => {
// Sign-in failed
showError('Sign-in Failed');
});
});
瀏覽器相容性
PasswordCredential
navigator.credentials.store()