Relogin dan HTTP Basic Auth

Pengembang web telah lama menyadari masalah masuk dan masuk ke situs yang dilindungi oleh Otorisasi Dasar HTTP. Meskipun ada metode otentikasi lain yang tidak menderita masalah ini, Otorisasi Dasar masih sering merupakan pilihan terbaik. Jaringan memiliki cukup bahan yang menggambarkan berbagai solusi umum dan khusus. Tetapi semuanya, yang saya temukan, sayangnya, hanya menggambarkan beberapa solusi parsial yang bekerja di satu browser dan tidak berfungsi di browser lain. Di bawah kucing saya memberikan hasil akhir umum dari penelitian saya tentang masalah ini

Saya akan segera membuat reservasi bahwa saya bukan pengembang front-end, dan saya tidak masuk ke berbagai "merek" dan versi browser. Hanya arus utama dengan versi yang relevan pada saat penulisan. Untuk sebagian besar tugas web ini sudah cukup. Bagi para pengembang yang membutuhkan dukungan untuk seluruh "kebun binatang" peramban, artikel ini bisa menjadi titik awal yang baik.

Inti masalahnya adalah bahwa standar Otorisasi Dasar HTTP tidak menyediakan kemungkinan razlogin. Umumnya. Ketika Anda pergi ke halaman yang dilindungi oleh Otorisasi Dasar, browser itu sendiri menampilkan Anda sendiri jendela dengan permintaan untuk login / kata sandi dan, dengan login yang berhasil, menyimpannya di suatu tempat di kedalamannya. Kemudian, semua permintaan berikutnya ke halaman lain yang dilindungi dari situs ini akan secara otomatis menggunakan nilai-nilai ini di header Otorisasi:
Otorisasi: Basic bm9uZTpub25l
di mana bm9uZTpub25l adalah tautan login / kata sandi yang dikodekan base64: tidak ada (nama pengguna dan kata sandi Anda mungkin berbeda)

Untuk masuk, Anda hanya perlu mengatur ulang nama pengguna / kata sandi lama di kedalaman browser dan di dalamnya tempat untuk merekam yang baru. Di sinilah kejutan menunggu kita. Karena tidak ada standar yang mengatur tindakan ini, setiap browser melakukan ini berdasarkan pemahamannya sendiri.

Lebih buruk lagi, karena jendela permintaan login / kata sandi adalah jendela perambannya sendiri, yang sudah merespons hanya tajuk halaman HTTP, jendela ini muncul sebelum pemrosesan badan laman apa pun. Artinya, untuk mengeksekusi beberapa javascript ketika menerima respons server dengan status 401 tidak berfungsi. Sebelum pengguna jendela ini akan muncul berulang kali dengan permintaan login / kata sandi berulang.

Faktanya, poin ini sangat penting, karena untuk hampir semua browser, satu-satunya cara untuk keluar adalah dengan mengirim permintaan ke server dengan login / kata sandi yang salah, menerima respons server dengan status 401 dan kemudian mereset cache login / kata sandi browser. Tetapi jika pada saat yang sama peramban tidak memungkinkan Anda untuk memproses respons 401 dan melanjutkan proses login sudah untuk pengguna baru, mengambil kendali bahkan pada tahap membaca header HTTP dan melemparkan bentuk otorisasi yang Anda masukkan tidak akan bekerja di wajah Anda, maka ini sudah menjadi masalah. Tidak masalah jika ini adalah permintaan normal dengan referensi atau XMLHttpRequest atau ambil. Browser masih mengambil kendali pada tahap penguraian header.

Begitu…

Data awal:


  1. Ada halaman logout.html terpisah di mana semua logika terletak di skrip javascript, yang sebagian diberikan dalam proses presentasi
  2. URL yang ditentukan - alamat halaman untuk dialihkan setelah login berhasil
  3. Url401 ditentukan - alamat halaman yang selalu mengembalikan kesalahan HTTP 401 (tidak diotorisasi)

// file logout.html
const url = new URL("http://mysite.com/");
const url401 = new URL("http://mysite.com/401");

Internet Explorer


Produk kami tidak memerlukan dukungan untuk browser ini, jadi solusi yang saya belum diuji secara pribadi. Namun demikian, menurut Google, ada solusi untuk itu, dan itu mungkin yang paling sederhana dan paling elegan dari semuanya. Selain itu, saya belum pernah bertemu informasi apa pun bahwa solusi untuk peramban Microsoft ini kehilangan relevansinya:

if (document.execCommand("ClearAuthenticationCache")) {
    window.location.assign(url);
}

Di IE, ada metode ClearAuthenticationCache yang membuang "usus yang sangat dalam." Sederhana dan elegan. Dan tidak ada menari dengan halaman tambahan 401. Saya tidak tahu apakah metode ini bekerja di Edge. Mungkin iya.

Construk document.execCommand mengembalikan true jika metode ada dan "bekerja". Kemudian window.location.assign (url) mengarahkan ulang pengguna untuk memasukkan nama pengguna dan kata sandi baru

Firefox (72.0.1)


Dalam konteks tugas kami, ini adalah peramban yang paling bermasalah. Baginya, solusi lengkap masih belum ada. Selama 15-20 tahun, permintaan untuk masalah yang ditunjukkan telah tergantung pada pelacak bug tim pengembangnya. Tapi "semuanya masih ada di sana." Maksimum yang bisa dicapai adalah kurva razlogin.

Input:
Firefox tidak mereset cache kata sandi setelah menerima respons 401 melalui XMLHttpRequest atau mengambil permintaan. Hanya melalui permintaan reguler dengan login / kata sandi di URL itu sendiri. Yaitu, kira-kira seperti itu
http: // tidak ada: none@mysite.com/
Kode:

else if (/firefox|iceweasel|fxios/i.test(window.navigator.userAgent)) {
    url.username = 'none';
    url.password = 'none';
    window.location.assign(url);
}

Setelah itu pengguna menerima formulir input login / kata sandi, di mana apa pun yang Anda masukkan, itu akan muncul lagi dan lagi. Faktanya adalah bahwa nilai yang dimasukkan tidak akan menimpa nilai login / kata sandi yang ditentukan dalam URL. Artinya, alih-alih nilai yang dimasukkan, banyak tidak ada: tidak ada yang akan pergi ke server setiap kali. Dan untuk masuk dengan nama yang berbeda, pengguna harus mengklik batal, pergi ke halaman awal (http: //mysite.com/) dan masukkan login / kata sandi baru di sana.

Bengkok? Namun sayang, tidak ada solusi lain

Google Chrome (79.0.3945.88)


Untuk Chrome, metode ambil berfungsi dengan baik. Tetapi XMLHttpRequest tidak berfungsi (((Cache tidak diatur ulang, dan logging tidak terjadi. Selain itu, saya mencoba mengatur login / kata sandi sebagai parameter untuk metode terbuka dan pengaturan header).

else if (/chrome/i.test(window.navigator.userAgent)) {
    fetch(url401, {
      credentials: 'include',
      headers: {
        'Authorization': 'Basic ' + btoa('none:none'),
        'X-Requested-With': 'XMLHttpRequest'
      }
    }).then(() => {
      window.location.assign(url);
    }).catch(err => console.error(err));
}

Kami membuat permintaan pengambilan ke halaman 401 dengan nama pengguna / kata sandi yang jelas salah, kami mendapatkan respons 401 dari server, browser mem-flush cache-nya.

PENTING! Server TIDAK boleh mengembalikan header WWW-Authenticate . Jika tidak, browser akan mengambil kendali, dan pengalihan dari halaman 401 tidak akan pernah terjadi. Secara konvensi, server tidak boleh mengembalikan header ini jika X-Requested-With: XMLHttpRequest ditentukan dalam permintaan . Oleh karena itu, tajuk X-Diminta-Dengan telah ditambahkan ke permintaan .

Safari (12)


Untuk Safari, situasinya justru sebaliknya: XMLHttpRequest berfungsi, tetapi pengambilan tidak berfungsi

else {
    const xhr = new XMLHttpRequest();
    xhr.open("GET", url401, true, 'none', 'none');
    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
    xhr.onerror = function(err) {
      console.error(err);
    };
    xhr.onload = function () {
      window.location.assign(url);
    };
    xhr.send()
}

Tindakannya sama seperti di Chrome, hanya melalui XMLHttpRequest

Harus bekerja untuk versi Safari 6+. Versi sebelumnya memiliki bug sendiri. Secara khusus, misalnya, dalam versi dari 5.1, dengan setiap pengalihan, browser secara paksa meminta kembali otorisasi, itulah sebabnya otorisasi dengan pengalihan ke halaman akhir pada prinsipnya tidak bekerja. Dan dalam versi sebelum 5.0, logging tidak berfungsi.

All Articles