การอัปเดตล่าสุดของ API การจัดการข้อมูลเข้าสู่ระบบ

ข้อมูลอัปเดตบางส่วนที่อธิบายไว้ที่นี่มีอธิบายไว้ในเซสชัน Google I/O การลงชื่อเข้าใช้ที่ปลอดภัยและราบรื่น: การทำให้ผู้ใช้มีส่วนร่วมอยู่เสมอ:

Chrome 57

Chrome 57 ได้เริ่มใช้การเปลี่ยนแปลงที่สำคัญนี้ใน API การจัดการข้อมูลเข้าสู่ระบบ

คุณแชร์ข้อมูลเข้าสู่ระบบจากโดเมนย่อยอื่นได้

ตอนนี้ Chrome สามารถเรียกข้อมูลเข้าสู่ระบบที่เก็บไว้ในโดเมนย่อยอื่นโดยใช้ API การจัดการข้อมูลเข้าสู่ระบบ เช่น หากจัดเก็บรหัสผ่านไว้ใน login.example.com สคริปต์ใน www.example.com สามารถแสดงเป็นหนึ่งในรายการบัญชีในกล่องโต้ตอบตัวเลือกบัญชี

คุณต้องจัดเก็บรหัสผ่านอย่างชัดแจ้งโดยใช้ navigator.credentials.store() เมื่อผู้ใช้เลือกข้อมูลเข้าสู่ระบบโดยแตะที่กล่องโต้ตอบ รหัสผ่านจะถูกส่งผ่านและคัดลอกไปยังต้นทางปัจจุบัน

เมื่อจัดเก็บไว้แล้ว คุณจะใช้รหัสผ่านเป็นข้อมูลเข้าสู่ระบบได้ ในต้นทางเดียวกันตั้งแต่ www.example.com เป็นต้นไป

ในภาพหน้าจอต่อไปนี้ ข้อมูลเข้าสู่ระบบที่จัดเก็บไว้ใน login.aliexpress.com m.aliexpress.com มองเห็นได้ และมีให้ผู้ใช้เลือก

วันที่ ตัวเลือกบัญชีผู้ใช้แสดงรายละเอียดการเข้าสู่ระบบโดเมนย่อยที่เลือกไว้

Chrome 60

Chrome 60 มีการเปลี่ยนแปลงที่สำคัญหลายอย่างกับ API การจัดการข้อมูลเข้าสู่ระบบ:

ต้องดำเนินการตรวจหาฟีเจอร์

เพื่อดูว่า API การจัดการข้อมูลเข้าสู่ระบบสำหรับเข้าถึงแบบใช้รหัสผ่านหรือไม่ และ ข้อมูลเข้าสู่ระบบแบบรวมศูนย์พร้อมใช้งาน โปรดตรวจสอบว่า window.PasswordCredential หรือ window.FederatedCredential ว่างอยู่

if (window.PasswordCredential || window.FederatedCredential) {
  // The Credential Management API is available
}

ตอนนี้ออบเจ็กต์ PasswordCredential รายการมีรหัสผ่านแล้ว

API การจัดการข้อมูลเข้าสู่ระบบใช้แนวทางที่เข้มงวดในการจัดการรหัสผ่าน เครื่องมือนี้ปกปิดรหัสผ่านจาก JavaScript ทำให้นักพัฒนาซอฟต์แวร์ต้อง เพื่อส่งออบเจ็กต์ PasswordCredential ไปยังเซิร์ฟเวอร์โดยตรง สำหรับการตรวจสอบผ่านส่วนขยายไปยัง fetch() API

แต่วิธีนี้ทำให้มีข้อจำกัดหลายอย่าง เราได้รับความคิดเห็นว่านักพัฒนาแอปใช้ API นี้ไม่ได้เนื่องจากเหตุผลต่อไปนี้

  • แต่ต้องส่งรหัสผ่านเป็นส่วนหนึ่งของออบเจ็กต์ JSON

  • ผู้ดูแลระบบจึงต้องส่งค่าแฮชของรหัสผ่านไปยังเซิร์ฟเวอร์ของตน

หลังดำเนินการวิเคราะห์ความปลอดภัยและทราบว่ามีการปิดบังรหัสผ่าน จาก JavaScript ไม่ได้ป้องกันเวกเตอร์การโจมตีทั้งหมด อย่างมีประสิทธิภาพอย่างที่เราคาดหวังไว้ เราได้ตัดสินใจที่จะทำการเปลี่ยนแปลง

ตอนนี้ 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

จนถึง 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() แล้ว

เพื่อให้สอดคล้องกับพร็อพเพอร์ตี้ 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://*****'
    }
});

คำแนะนำในการย้ายข้อมูล

มีการใช้งาน API การจัดการข้อมูลเข้าสู่ระบบอยู่แล้วใช่ไหม เรามีเอกสารคำแนะนำในการย้ายข้อมูล ก็สามารถอัปเกรดเป็นเวอร์ชันใหม่ได้