การอัปเดตบางส่วนที่อธิบายไว้ในบทความนี้ได้อธิบายไว้ในเซสชัน Google I/O การลงชื่อเข้าใช้ที่ปลอดภัยและราบรื่น: การทำให้ผู้ใช้มีส่วนร่วมอย่างต่อเนื่อง:
Chrome 57
Chrome 57 นำเสนอการเปลี่ยนแปลงที่สำคัญนี้ใน API การจัดการข้อมูลเข้าสู่ระบบ
ข้อมูลเข้าสู่ระบบสามารถแชร์จากโดเมนย่อยอื่นได้
ตอนนี้ Chrome เรียกข้อมูลเข้าสู่ระบบที่จัดเก็บไว้ในโดเมนย่อยอื่นได้โดยใช้ Credential Management API แล้ว
ตัวอย่างเช่น หากเก็บรหัสผ่านไว้ในlogin.example.com
สคริปต์ใน www.example.com
จะแสดงรหัสผ่านดังกล่าวเป็นหนึ่งในรายการบัญชีในกล่องโต้ตอบตัวเลือกบัญชีได้
คุณต้องจัดเก็บรหัสผ่านไว้อย่างชัดแจ้งโดยใช้ navigator.credentials.store()
เพื่อที่ว่าเมื่อผู้ใช้เลือกข้อมูลเข้าสู่ระบบโดยแตะกล่องโต้ตอบ ระบบจะส่งรหัสผ่านและคัดลอกไปยังต้นทางปัจจุบัน
เมื่อจัดเก็บแล้ว รหัสผ่านจะแสดงเป็นข้อมูลเข้าสู่ระบบใน www.example.com
ต้นทางเดียวกันเป็นต้นไป
ในภาพหน้าจอต่อไปนี้ m.aliexpress.com
จะเห็นข้อมูลเข้าสู่ระบบที่จัดเก็บไว้ใน login.aliexpress.com
และให้ผู้ใช้เลือกได้
Chrome 60
Chrome 60 ทำให้เกิดการเปลี่ยนแปลงที่สำคัญหลายอย่างใน API การจัดการข้อมูลเข้าสู่ระบบ ดังนี้
เนื่องจากไม่จำเป็นต้องมีฟังก์ชัน
fetch()
ที่กำหนดเองในการดึงข้อมูลรหัสผ่านอีกต่อไป เราจะเลิกใช้งานฟังก์ชันดังกล่าวเร็วๆ นี้navigator.credentials.get()
ยอมรับ enummediation
แล้ว แทนแฟล็กบูลีนunmediated
requireUserMediation()
เปลี่ยนชื่อเป็นpreventSilentAccess()
เมธอดใหม่
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 จะมีรหัสผ่านแบบ Raw ในออบเจ็กต์ข้อมูลเข้าสู่ระบบที่ส่งกลับอยู่ เพื่อให้คุณเข้าถึงรหัสผ่านแบบข้อความธรรมดาได้ คุณสามารถใช้วิธีการที่มีอยู่เพื่อส่งข้อมูลเข้าสู่ระบบไปยังเซิร์ฟเวอร์ของคุณ โดยทำดังนี้
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()
ยอมรับสื่อกลาง enum แล้ว
navigator.credentials.get()
ยอมรับพร็อพเพอร์ตี้ unmediated
ที่ไม่บังคับที่มีแฟล็กบูลีนจนถึง Chrome 60 แล้ว เช่น
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()
แล้ว
เพื่อให้สอดคล้องกับพร็อพเพอร์ตี้ mediation
ใหม่ที่เสนอในการโทร get()
เราได้เปลี่ยนชื่อเมธอด 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 อยู่แล้ว เรามีเอกสารคำแนะนำในการย้ายข้อมูล ที่คุณสามารถทำตามเพื่ออัปเกรดเป็นเวอร์ชันใหม่