การอัปเดตบางอย่างที่อธิบายไว้ที่นี่มีคำอธิบายอยู่ในเซสชัน 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 เห็นและพร้อมให้ผู้ใช้เลือก
Chrome 60
Chrome 60 มีการเปลี่ยนแปลงที่สำคัญหลายอย่างใน Credential Management API ดังนี้
ตอนนี้ออบเจ็กต์
PasswordCredentialมีรหัสผ่านแล้วเนื่องจากไม่จำเป็นต้องใช้ฟังก์ชัน
fetch()ที่กําหนดเองเพื่อดึงข้อมูลรหัสผ่านอีกต่อไป เราจะเลิกใช้งานฟังก์ชันนี้ในเร็วๆ นี้navigator.credentials.get()ยอมรับ enummediationแทน Flag บูลีน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 มีรหัสผ่านดิบอยู่ในออบเจ็กต์ข้อมูลเข้าสู่ระบบที่แสดงผลเพื่อให้คุณเข้าถึงรหัสผ่านดังกล่าวในรูปแบบข้อความธรรมดาได้ คุณสามารถใช้วิธีการที่มีอยู่เพื่อส่งข้อมูลเข้าสู่ระบบไปยังเซิร์ฟเวอร์ได้ ดังนี้
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 แล้ว
จนถึง Chrome 60
navigator.credentials.get() ยอมรับพร็อพเพอร์ตี้ unmediated ที่ไม่บังคับ
ด้วย Flag บูลีน เช่น
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
unmediated: true
}).then(c => {
// Sign-in
});
การตั้งค่า unmediated: true ป้องกันไม่ให้เบราว์เซอร์แสดงเครื่องมือเลือกบัญชีเมื่อส่งข้อมูลเข้าสู่ระบบ
ตอนนี้การแจ้งว่าไม่เหมาะสมได้ขยายการให้บริการเป็นสื่อกลางแล้ว การสื่อกลางของผู้ใช้อาจเกิดขึ้นในกรณีต่อไปนี้
ผู้ใช้ต้องเลือกบัญชีที่จะลงชื่อเข้าใช้
ผู้ใช้ต้องการลงชื่อเข้าใช้อย่างชัดเจนหลังจาก
navigator.credentials.requireUseMediation()โทร
เลือกตัวเลือกใดตัวเลือกหนึ่งต่อไปนี้สำหรับค่า mediation
ค่า mediation |
เมื่อเทียบกับ Flag แบบบูลีน | พฤติกรรม | |
|---|---|---|---|
silent |
เท่ากับ unmediated: true |
ส่งข้อมูลเข้าสู่ระบบโดยไม่ได้แสดงเครื่องมือเลือกบัญชี | |
optional |
เท่ากับ unmediated: false |
แสดงเครื่องมือเลือกบัญชีหากเรียกใช้ preventSilentAccess() ก่อนหน้านี้ |
|
required |
ตัวเลือกใหม่ | แสดงเครื่องมือเลือกบัญชีเสมอ มีประโยชน์เมื่อคุณต้องการอนุญาตให้ผู้ใช้เปลี่ยนบัญชีโดยใช้กล่องโต้ตอบตัวเลือกบัญชีแบบดั้งเดิม |
ในตัวอย่างนี้ ระบบจะส่งผ่านข้อมูลเข้าสู่ระบบโดยไม่แสดงเครื่องมือเลือกบัญชี ซึ่งเทียบเท่ากับ Flag ก่อนหน้า unmediated: true
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
mediation: 'silent'
}).then(c => {
// Sign-in
});
เปลี่ยนชื่อ requireUserMediation() เป็น preventSilentAccess()
เราได้เปลี่ยนชื่อเมธอด navigator.credentials.requireUserMediation() เป็น navigator.credentials.preventSilentAccess() เพื่อให้สอดคล้องกับพร็อพเพอร์ตี้ mediation ใหม่ที่เสนอในการเรียก get()
เมธอดที่เปลี่ยนชื่อจะป้องกันไม่ให้ส่งข้อมูลเข้าสู่ระบบโดยไม่แสดงเครื่องมือเลือกบัญชี (บางครั้งเรียกว่า "ไม่มีสื่อกลางของผู้ใช้") ซึ่งจะมีประโยชน์เมื่อผู้ใช้ออกจากระบบเว็บไซต์หรือยกเลิกการลงทะเบียนในเว็บไซต์ และไม่ต้องการลงชื่อเข้าใช้อีกครั้งโดยอัตโนมัติเมื่อเข้าชมครั้งถัดไป
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 อยู่แล้วใช่ไหม เรามีเอกสารคำแนะนำในการย้ายข้อมูลไว้ให้คุณทำตามเพื่ออัปเกรดเป็นเวอร์ชันใหม่