การอัปเดตบางอย่างที่อธิบายไว้ที่นี่มีคำอธิบายอยู่ในเซสชัน 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 ดังนี้
เนื่องจากไม่จำเป็นต้องใช้ฟังก์ชัน
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 มีรหัสผ่านดิบในออบเจ็กต์ข้อมูลเข้าสู่ระบบที่แสดงผล คุณจึงเข้าถึงรหัสผ่านดังกล่าวเป็นข้อความธรรมดาได้ คุณสามารถใช้วิธีการที่มีอยู่เพื่อส่งข้อมูลเข้าสู่ระบบไปยังเซิร์ฟเวอร์ได้ ดังนี้
navigator.credentials.get({
password: true,
federated: {
providers: [ 'https://accounts.google.com' ]
},
mediation: 'silent'
}).the>n(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 ที่ไม่บังคับซึ่งมีแฟล็กบูลีน เช่น
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&>#39;
}).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: 39;https://*****'
}
});
คำแนะนำในการย้ายข้อมูล
หากติดตั้งใช้งาน Credential Management API อยู่แล้ว เรามีเอกสารคำแนะนำในการย้ายข้อมูลที่คุณสามารถทำตามเพื่ออัปเกรดเป็นเวอร์ชันใหม่ได้