Bagaimana cara mencegah browser memanggil popup auth dasar dan menangani kesalahan 401 menggunakan Jquery?

Jawaban:

46

Saya juga menghadapi masalah ini baru-baru ini. Karena Anda tidak dapat mengubah perilaku default browser untuk menampilkan munculan dalam kasus 401( otentikasi dasar atau intisari ), ada dua cara untuk memperbaikinya:

  • Ubah respons server untuk tidak mengembalikan a 401. Kembalikan 200kode sebagai gantinya dan tangani ini di klien jQuery Anda.
  • Ubah metode yang Anda gunakan untuk otorisasi menjadi nilai khusus di header Anda. Browser akan menampilkan popup untuk Basic dan Intisari . Anda harus mengubah ini pada klien dan server.

    headers : {
      "Authorization" : "BasicCustom"
    }
    

Silakan lihat ini juga untuk contoh penggunaan jQuery dengan Basic Auth.

nwinkler
sumber
10
WWW-Authenticate: xBasic realm = com.example dapat melakukannya, bersama dengan kode status 401 klasik. posting blog ini menunjukkan kepada saya petunjuknya (Saya bukan pemilik blog) loudvchar.blogspot.ca/2010/11/…
PM
2
@PM, jawaban blog adalah solusi yang tepat. Perhatikan bahwa jika menggunakan <security:http-basic/>Anda tidak perlu mendefinisikan basicAuthenticationFiltertetapi harus mendefinisikannya sebagai <security:http-basic entry-point-ref="myBasicAuthenticationEntryPoint"/>.
Brett Ryan
Tolong beri tahu saya cara mengganti respons sebelum mengirim kembali ke klien, saya menggunakan jaxrs dengan autentikasi dasar. kelas mana yang perlu saya ganti untuk mengubah respons?
mohammed sameen
Untuk beberapa alasan saya mendapatkan munculan ketika mengembalikan a 401dan WWW-Authenticate:Bearer WWW-Authenticate:NTLM WWW-Authenticate:NegotiateApakah Anda tahu mengapa itu terjadi
DevEng
34

Kembalikan kode status 400 generik, dan kemudian proses sisi klien tersebut.

Atau Anda dapat menyimpan 401, dan tidak mengembalikan header WWW-Authenticate, yang sebenarnya merupakan respons browser dengan popup otentikasi. Jika header WWW-Authenticate hilang, browser tidak akan meminta kredensial.

Ibraheem
sumber
6
@MortenHaraldsen Jawaban 401 adalah respon yang tepat untuk diberikan dalam kesempatan ini, masalahnya adalah bahwa browser secara otomatis menangani ini secara native, daripada mengizinkan aplikasi javascript untuk menanganinya. Anda dapat tetap berpegang pada standar, dengan tidak mengembalikan tanggapan yang tepat seperti yang direkomendasikan standar, atau Anda dapat memilih untuk tidak mengikuti standar, dengan mengembalikan kode tanggapan yang disarankan standar. Silakan pilih :)
Ibraheem
Di aplikasi ekspres saya, saya memperbaikinya dengan satu baris: res.removeHeader('www-authenticate'); // prevents browser from popping up a basic auth window.
gstroup
1
@Ibraheem, tidak bisa mengatakannya dengan lebih baik sendiri. Standar dibuat oleh orang-orang yang duduk dan berbicara, tidak harus mereka yang duduk dan membuat kode.
pengguna2867288
15

Anda dapat menyembunyikan munculan autentikasi dasar dengan url permintaan yang terlihat seperti ini:

https://username:[email protected]/admin/...

Jika Anda mendapatkan kesalahan 401 (nama pengguna atau kata sandi salah) itu akan ditangani dengan benar dengan panggilan balik kesalahan jquery. Ini dapat menyebabkan beberapa masalah keamanan (dalam kasus protokol http, bukan https), tetapi berfungsi.

UPD: Dukungan solusi ini akan dihapus di Chrome 59

Ivan Samovar
sumber
LUAR BIASA !!!! Memecahkan masalah saya karena masalah mencoba 192.168.1.1 dan router terus meminta Auth.
Nadav Lebovitch
Jika Anda membuka tab "Jaringan" di bawah alat Pengembang, di browser apa pun, Anda dapat membaca nama pengguna dan sandi dalam teks biasa. Itu berhasil.
Bruno Finger
19
Jangan pernah melakukan ini, permintaan log di server web Anda jauh lebih berharga bagi saya sekarang .. Nama pengguna dan sandi kombo gratis ditambah kode respons! Terima kasih
Remco
tetapi bagaimana seseorang dapat mencegah nama pengguna dan kata sandi dilihat
sdx11
3
Metode otentikasi ini semakin disusutkan dan Chrome akan menghentikan dukungan untuk kredensial yang disematkan yaitu https://user:pass@host/di M59 sekitar Juni 2017. Lihat entri blog chromestatus ini untuk info lebih lanjut.
Garywoo
13

Seperti yang ditunjukkan orang lain, satu-satunya cara untuk mengubah perilaku browser adalah memastikan respons tidak berisi kode status 401 atau jika ya, tidak menyertakan WWW-Authenticate: Basicheader. Karena mengubah kode status sangat tidak semantik dan tidak diinginkan, pendekatan yang baik adalah dengan menghapus WWW-Authenticateheader. Jika Anda tidak dapat atau tidak ingin mengubah aplikasi server web Anda, Anda selalu dapat melayani atau mem-proxy-nya melalui Apache (jika Anda belum menggunakan Apache).

Berikut adalah konfigurasi bagi Apache untuk menulis ulang respons untuk menghapus header WWW-Authenticate IFF yang berisi permintaan berisi header X-Requested-With: XMLHttpRequest(yang disetel secara default oleh kerangka kerja Javascript utama seperti JQuery / AngularJS, dll ...) DAN respons berisi header WWW-Authenticate: Basic.

Diuji pada Apache 2.4 (tidak yakin apakah berfungsi dengan 2.2). Ini bergantung pada mod_headersmodul yang dipasang. (Di Debian / Ubuntu, sudo a2enmod headersdan mulai ulang Apache)

    <Location />
            # Make sure that if it is an XHR request,
            # we don't send back basic authentication header.
            # This is to prevent the browser from displaying a basic auth login dialog.
            Header unset WWW-Authenticate "expr=req('X-Requested-With') == 'XMLHttpRequest' && resp('WWW-Authenticate') =~ /^Basic/"
    </Location>   
syastrov.dll
sumber
1
Untuk melakukan hal yang sama dengan Nginx, setelproxy_hide_header WWW-Authenticate;
Cuga
7

Gunakan X-Requested-With: XMLHttpRequest dengan header permintaan Anda. Jadi header respons tidak akan berisi WWW-Authenticate: Basic.

beforeSend: function (xhr) {
                    xhr.setRequestHeader('Authorization', ("Basic "
                        .concat(btoa(key))));
                    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                },
sedhu
sumber
1
Itu tidak berpengaruh bagi saya. Jenis server apa yang Anda gunakan yang WWW-Authenticate tidak terkirim disertakan saat Anda menyetel XMLHttpRequest?
Robert Antonucci
@RobertAntonucci ini apache tomcat
sedhu
5

Jika Anda menggunakan Server IIS, Anda dapat mengatur IIS URL Rewriting (v2) untuk menulis ulang WWW-Authenticationheader ke Nonepada URL yang diminta.

Pandu di sini .

Nilai yang ingin Anda ubah adalah response_www_authenticate.

Jika Anda membutuhkan info lebih lanjut, tambahkan komentar dan saya akan memposting file web.config.

Zymotik
sumber
1
Ini berhasil dengan baik. Saya ingin mencatat bahwa bagian "respon" harus ditulis sebagai "RESPONSE_www_authenticate" di URL Rewrite v2 di IIS 7.5.
Michael Freeman
3

Jika header WWW-Authenticate dihapus, maka Anda tidak akan mendapatkan caching kredensial dan tidak akan mendapatkan kembali header Otorisasi sesuai permintaan. Itu berarti sekarang Anda harus memasukkan kredensial untuk setiap permintaan baru yang Anda buat.

pengguna2491441
sumber
Ini sangat penting, sangat tepat.
Tez Wingfield
2

Atau, jika Anda dapat menyesuaikan respons server, Anda dapat mengembalikan 403 Forbidden.

Browser tidak akan membuka popup otentikasi dan jquery callback akan dipanggil.

Javier Ferrero
sumber
5
Hal itu bertentangan dengan spesifikasi HTTP 1.1, yang menyatakan bahwa "... Otorisasi tidak akan membantu dan permintaan TIDAK HARUS diulangi".
Jukka Dahlbom
1
Adalah sah untuk menerima 403 sementara diautentikasi untuk sumber daya yang tidak boleh Anda akses, 401 harus dikirim ke tempat yang belum Anda autentikasi.
Brett Ryan
1

Di Safari, Anda dapat menggunakan permintaan sinkron untuk menghindari browser menampilkan popup. Tentu saja, permintaan sinkron hanya boleh digunakan dalam kasus ini untuk memeriksa kredensial pengguna ... Anda dapat menggunakan permintaan tersebut sebelum mengirim permintaan sebenarnya yang dapat menyebabkan pengalaman pengguna yang buruk jika konten (dikirim atau diterima) cukup berat.

    var xmlhttp=new XMLHttpRequest;
    xmlhttp.withCredentials=true;
    xmlhttp.open("POST",<YOUR UR>,false,username,password);
    xmlhttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
    xmlhttp.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
Emmanuel Sellier
sumber
Dalam konteks lain, menggunakan "OPTIONS" sebagai ganti "POST" juga dapat membantu.
Emmanuel Sellier
0

Buat / login url, lalu terima parameter "user" dan "password" melalui GET dan tidak memerlukan autentikasi dasar. Di sini, gunakan php, node, java, apapun dan parsing file passwd Anda dan cocokkan parameter (user / pass) terhadapnya. Jika ada kecocokan maka redirect ke http: // user: [email protected]/ (ini akan mengatur kredensial pada browser Anda) jika tidak, kirim respon 401 (tanpa header WWW-Authenticate).

neiker
sumber
Itu akan sangat bagus untuk siapa saja yang mencoba mengendus nama pengguna / kata sandi dari orang teks biasa di tengah serangan!
Ajax
0

Dari sisi belakang dengan Spring Boot, saya telah menggunakan BasicAuthenticationEntryPoint kustom:

@Override
protected void configure(HttpSecurity http) throws Exception {
    http.cors().and().authorizeRequests()
            ...
            .antMatchers(PUBLIC_AUTH).permitAll()
            .and().httpBasic()
//    https://www.baeldung.com/spring-security-basic-authentication
            .authenticationEntryPoint(authBasicAuthenticationEntryPoint())
            ...

@Bean
public BasicAuthenticationEntryPoint authBasicAuthenticationEntryPoint() {
    return new BasicAuthenticationEntryPoint() {
        {
            setRealmName("pirsApp");
        }

        @Override
        public void commence
                (HttpServletRequest request, HttpServletResponse response, AuthenticationException authEx)
                throws IOException, ServletException {
            if (request.getRequestURI().equals(PUBLIC_AUTH)) {
                response.sendError(HttpStatus.PRECONDITION_FAILED.value(), "Wrong credentials");
            } else {
                super.commence(request, response, authEx);
            }
        }
    };
}
Grigory Kislin
sumber