Tarayıcının Jquery kullanarak temel kimlik doğrulama açılır penceresini çağırması ve 401 hatasını işlemesi nasıl engellenir?


107

Temel yetkilendirmeyi kullanarak yetkilendirme isteği göndermem gerekiyor. Bunu jquery kullanarak başarıyla uyguladım. Ancak 401 hatası aldığımda temel kimlik doğrulama tarayıcısı açılır penceresi açılıyor ve jquery ajax hatası geri araması çağrılmıyor.


Yanıtlar:


46

Son zamanlarda ben de bu sorunla karşı karşıyaydım. Bir 401( temel veya özet kimlik doğrulama) durumunda tarayıcının varsayılan pop-up gösterme davranışını değiştiremeyeceğiniz için , bunu düzeltmenin iki yolu vardır:

  • Sunucu yanıtını bir döndürmeyecek şekilde değiştirin 401. 200Bunun yerine bir kod döndürün ve bunu jQuery istemcinizde işleyin.
  • Yetkilendirme için kullandığınız yöntemi başlığınızdaki özel bir değerle değiştirin. Tarayıcılar, Temel ve Özet için açılır pencereyi görüntüleyecektir . Bunu hem istemcide hem de sunucuda değiştirmeniz gerekir.

    headers : {
      "Authorization" : "BasicCustom"
    }

Ayrıca bir göz atın lütfen bu Basic Auth ile jQuery kullanarak bir örnek için.


10
WWW-Authenticate: xBasic realm = com.example, klasik 401 durum koduyla birlikte bunu yapabilir. bu blog yazısı bana ipucu gösterdi (blogun sahibi değilim) loudvchar.blogspot.ca/2010/11/…
PM

2
@ PM, blogun cevabı mükemmel bir çözüm. Kullanıyorsanız <security:http-basic/>tanımlamanıza gerek olmadığını, basicAuthenticationFilterancak olarak tanımlamanız gerektiğini unutmayın <security:http-basic entry-point-ref="myBasicAuthenticationEntryPoint"/>.
Brett Ryan

Lütfen istemciye geri göndermeden önce yanıtı nasıl geçersiz kılacağımı söyler misiniz, temel kimlik doğrulamalı jaxrs kullanıyorum. Yanıtı değiştirmek için hangi sınıfı geçersiz kılmam gerekiyor?
mohammed sameen

Bir nedenden ötürü, 401WWW-Authenticate:Bearer WWW-Authenticate:NTLM WWW-Authenticate:Negotiate
a'yı

34

Genel bir 400 durum kodu döndürün ve ardından bu istemci tarafını işleyin.

Ya da 401'i saklayabilir ve WWW-Authenticate başlığını döndürmeyebilirsiniz, bu gerçekten tarayıcının kimlik doğrulama açılır penceresiyle yanıt verdiği şeydir. WWW-Authenticate başlığı eksikse, tarayıcı kimlik bilgileri istemez.


6
@MortenHaraldsen Bu durumda 401 yanıtı verilecek doğru yanıttır, sorun, tarayıcının bunu javascript uygulamasının işlemesine izin vermek yerine otomatik olarak yerel olarak ele almasıdır. Standardın önerdiği doğru yanıtı geri getirmeyerek standarda bağlı kalabilir veya standart önerilen yanıt kodunu döndürerek standarda bağlı kalmamayı seçebilirsiniz.
Seçiminizi

Ekspres uygulamamda bunu bir satırla düzelttim: res.removeHeader('www-authenticate'); // prevents browser from popping up a basic auth window.
gstroup

1
@Ibraheem, bunu kendimden daha iyi ifade edemezdim. Standartlar, mutlaka oturup kod yazanlar değil, oturup konuşan insanlar tarafından yaratılır.
user2867288

15

Aşağıdaki gibi görünen istek url'si ile temel kimlik doğrulama pop-up'ını engelleyebilirsiniz:

https://username:password@example.com/admin/...

401 hatası alırsanız (yanlış kullanıcı adı veya parola), jquery hatası geri aramasıyla doğru şekilde işlenecektir. Bazı güvenlik sorunlarına neden olabilir (https yerine http protokolü olması durumunda), ancak işe yarıyor.

UPD: Bu çözüm desteği Chrome 59'da kaldırılacaktır.


İNANILMAZ!!!! Sorun 192.168.1.1'i denediğinden ve yönlendirici Auth sormaya devam ettiğinden sorunumu çözdüm.
Nadav Lebovitch

Geliştirici araçlarının altındaki "Ağ" sekmesine giderseniz, herhangi bir tarayıcıda kullanıcı adını ve şifreyi düz metin olarak okuyabilirsiniz. Yine de çalışıyor.
Bruno Finger

19
Lütfen bunu asla yapmayın, web sunucunuzdaki istek günlükleri artık benim için çok daha değerli .. Ücretsiz kullanıcı adları ve şifre kombinasyonları artı yanıt kodu! Teşekkürler
Remco

ancak birisi kullanıcı adı ve parolanın görüntülenmesini nasıl engelleyebilir
sdx11

3
Bu kimlik doğrulama yöntemi artık kullanılmıyor ve Chrome, gömülü kimlik bilgileri desteğini bırakıyor, yani https://user:pass@host/Haziran 2017 civarında M59'da . Daha fazla bilgi için bu chromestatus blog gönderisine bakın .
Garywoo

13

Diğerlerinin de belirttiği gibi, tarayıcının davranışını değiştirmenin tek yolu, yanıtın bir 401 durum kodu içermediğinden veya içeriyorsa, WWW-Authenticate: Basicbaşlığı içermediğinden emin olmaktır . Durum kodunu değiştirmek çok anlamsal ve istenmeyen bir durum olmadığından, iyi bir yaklaşım,WWW-Authenticate başlığı . Web sunucusu uygulamanızı değiştiremiyorsanız veya değiştirmek istemiyorsanız, her zaman Apache aracılığıyla sunabilir veya proxy yapabilirsiniz (zaten Apache kullanmıyorsanız).

Burada, Apache'nin WWW-Authenticate üstbilgisini kaldırmak için yanıtı yeniden yazması için bir yapılandırma X-Requested-With: XMLHttpRequestbulunmaktadır. başlık WWW-Authenticate: Basic.

Apache 2.4 üzerinde test edilmiştir (2.2 ile çalışıp çalışmadığından emin değil). Bu, mod_headerskurulmakta olan modüle bağlıdır. (Debian / Ubuntu'da sudo a2enmod headersve Apache'yi yeniden başlatın)

    <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>   

1
Nginx ile aynı şeyi yapmak için, ayarlayınproxy_hide_header WWW-Authenticate;
Cuga

7

İstek başlığınızla X-Requested-With: XMLHttpRequest öğesini kullanın. Bu nedenle yanıt başlığı WWW-Authenticate: Basic içermeyecektir.

beforeSend: function (xhr) {
                    xhr.setRequestHeader('Authorization', ("Basic "
                        .concat(btoa(key))));
                    xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                },

1
Bunun benim için hiçbir etkisi olmadı. XMLHttpRequest'i ayarladığınızda WWW-Authenticate'in gönderilmediği ne tür bir sunucu kullanıyorsunuz?
Robert Antonucci

@RobertAntonucci it's apache tomcat
sedhu

5

Bir IIS Sunucusu kullanıyorsanız, WWW-Authenticationüstbilgiyi Noneistenen URL'ye yeniden yazmak için IIS URL Yeniden Yazma'yı (v2) kurabilirsiniz .

Burada rehberlik edin .

Değiştirmek istediğiniz değer response_www_authenticate.

Daha fazla bilgiye ihtiyacınız varsa, bir yorum ekleyin ve web.config dosyasını göndereceğim.


1
Bu harika çalıştı. IIS 7.5'teki URL Rewrite v2'de "yanıt" kısmının "RESPONSE_www_authenticate" olarak yazılması gerektiğini belirtmek isterim.
Michael Freeman

3

WWW-Authenticate başlığı kaldırılırsa, kimlik bilgilerinin önbelleğe alınmasını ve istekte Yetkilendirme başlığını geri alamazsınız. Bu, artık oluşturduğunuz her yeni istek için kimlik bilgilerini girmeniz gerektiği anlamına gelir.


Bu çok önemli, kesinlikle yerinde.
Tez Wingfield

2

Alternatif olarak, sunucu yanıtınızı özelleştirebiliyorsanız, 403 Yasak'ı döndürebilirsiniz.

Tarayıcı kimlik doğrulama açılır penceresini açmayacak ve jquery geri araması çağrılacaktır.


5
Bu, "... Yetkilendirmenin yardımcı olmayacağı ve istek tekrarlanmaması GEREKİR" ifadesinin belirtildiği HTTP 1.1 spesifikasyonuna aykırıdır.
Jukka Dahlbom

1
Erişim izniniz olmayan kaynaklar için kimlik doğrulaması yapılırken 403 almanız geçerlidir, henüz kimliğinizin doğrulanmadığı yerlere 401 gönderilmelidir.
Brett Ryan

1

Safari'de, tarayıcının açılır pencereyi görüntülemesini önlemek için eşzamanlı istekleri kullanabilirsiniz. Elbette, senkronize istekler yalnızca bu durumda kullanıcı kimlik bilgilerini kontrol etmek için kullanılmalıdır ... Bu tür bir isteği gerçek isteği göndermeden önce kullanabilirsiniz, bu da içerik (gönderilen veya alınan) oldukça ağırsa kötü bir kullanıcı deneyimine neden olabilir.

    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');

Diğer bağlamlarda, "POST" yerine "SEÇENEKLER" kullanmak da yardımcı olabilir.
Emmanuel Sellier

0

GET aracılığıyla "kullanıcı" ve "şifre" parametrelerini kabul etmek yerine bir / login url'si oluşturun ve temel kimlik doğrulama gerektirmez. Burada php, node, java vb. Kullanın ve passwd dosyanızı ayrıştırın ve parametreleri (kullanıcı / geçiş) ona karşı eşleştirin. Bir eşleşme varsa, http: // user: pass@domain.com/ adresine yönlendirin (bu, tarayıcınızda kimlik bilgilerini belirleyecektir), yoksa 401 yanıtı gönderin (WWW-Authenticate başlığı olmadan).


Bu, ortadaki saldırılarda düz metinli adamdan kullanıcı adı / şifreleri koklamaya çalışan herkes için harika olurdu!
Ajax

0

Spring Boot ile arka taraftan özel BasicAuthenticationEntryPoint kullandım:

@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);
            }
        }
    };
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.