web-dev-qa-db-fra.com

Comment empêcher le navigateur d'invoquer une popup automatique de base et de gérer l'erreur 401 à l'aide de Jquery?

Je dois envoyer une demande d'autorisation en utilisant l'authentification de base. J'ai réussi à implémenter cela en utilisant jquery. Cependant, lorsque je reçois une erreur 401, le popup de navigateur d’authentification de base s’ouvre et le rappel d’erreur jax ajax n’est pas appelé.

97
Alexey Zakharov

J'ai été confronté à ce problème récemment, aussi. Étant donné que vous ne pouvez pas modifier le comportement par défaut du navigateur consistant à afficher la fenêtre contextuelle dans le cas d'un 401 (( authentification de base ou ) ), il existe deux façons de répare ça:

  • Modifier la réponse du serveur pour ne pas renvoyer un 401. Retourne un 200 code à la place et gérez cela dans votre client jQuery.
  • Modifiez la méthode que vous utilisez pour l'autorisation en une valeur personnalisée dans votre en-tête. Les navigateurs affichent le menu contextuel pour Basique et Digest . Vous devez changer cela à la fois sur le client et sur le serveur.

    headers : {
      "Authorization" : "BasicCustom"
    }
    

Veuillez également consulter this pour obtenir un exemple d'utilisation de jQuery avec l'authentification de base.

41
nwinkler

Renvoie un code d'état générique 400, puis traite ce côté client.

Ou vous pouvez conserver le 401 sans renvoyer l'en-tête WWW-Authenticate, ce à quoi répond le navigateur avec le menu contextuel d'authentification. Si l'en-tête WWW-Authenticate est manquant, le navigateur ne demandera pas d'informations d'identification.

31
Ibraheem

Vous pouvez supprimer les popups d'authentification de base avec une URL de requête ressemblant à ceci:

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

Si vous obtenez une erreur 401 (nom d'utilisateur ou mot de passe incorrect), elle sera correctement gérée avec le rappel d'erreur jquery. Cela peut causer des problèmes de sécurité (dans le cas du protocole http au lieu de https), mais cela fonctionne.

PD: Cette assistance de la solution sera supprimée dans Chrome 59

17
Ivan Samovar

Comme d'autres l'ont fait remarquer, le seul moyen de modifier le comportement du navigateur est de s'assurer que la réponse ne contient pas de code d'état 401 ou, le cas échéant, n'inclut pas le WWW-Authenticate: Basic entête. Comme le changement de code de statut n’est pas très sémantique et indésirable, une bonne approche consiste à supprimer le WWW-Authenticate entête. Si vous ne pouvez ou ne voulez pas modifier votre application de serveur Web, vous pouvez toujours la servir ou la remplacer par proxy via Apache (si vous n'utilisez pas déjà Apache).

Voici une configuration permettant à Apache de réécrire la réponse pour supprimer l'en-tête WWW-Authenticate IFF que contient la demande contient l'en-tête X-Requested-With: XMLHttpRequest (défini par défaut par les principaux frameworks Javascript tels que JQuery/AngularJS, etc ...) ET la réponse contient l’en-tête WWW-Authenticate: Basic.

Testé sur Apache 2.4 (ne sait pas si cela fonctionne avec la version 2.2). Cela repose sur le mod_headers module en cours d'installation. (Sur Debian/Ubuntu, Sudo a2enmod headers et redémarrez 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>   
10
syastrov

Si vous utilisez un serveur IIS, vous pouvez configurer IIS Réécriture d'URL (v2) pour réécrire le WWW-Authentication en-tête à None sur l'URL demandée.

Guide ici .

La valeur que vous souhaitez modifier est response_www_authenticate.

Si vous avez besoin de plus d'informations, ajoutez un commentaire et je posterai le fichier web.config.

5
Zymotik

Utilisez X-Requested-With: XMLHttpRequest avec l'en-tête de votre demande. Donc, l'en-tête de réponse ne contiendra pas WWW-Authenticate: Basic.

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

Si l'en-tête WWW-Authenticate est supprimé, vous n'obtiendrez pas la mise en cache des informations d'identification et ne récupérerez pas l'en-tête Authorization dans la requête. Cela signifie que vous devez maintenant saisir les informations d'identification pour chaque nouvelle demande que vous générez.

2
user2491441

Sinon, si vous pouvez personnaliser la réponse de votre serveur, vous pouvez renvoyer un message 403 Forbidden.

Le navigateur n'ouvrira pas le menu contextuel d'authentification et le rappel jquery sera appelé.

2
Javier Ferrero

Dans Safari, vous pouvez utiliser des requêtes synchrones pour empêcher le navigateur d’afficher la fenêtre contextuelle. Bien entendu, les requêtes synchrones ne doivent être utilisées que dans ce cas pour vérifier les informations d'identification de l'utilisateur ... Vous pouvez utiliser une telle requête avant d'envoyer la requête réelle, ce qui peut entraîner une mauvaise expérience utilisateur si le contenu (envoyé ou reçu) est assez lourd.

    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');
1
Emmanuel Sellier

De l'arrière avec Spring Boot j'ai utilisé personnalisé BasicAuthenticationEntryPoint:

@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);
            }
        }
    };
}
0
GKislin

Créez une URL/login, puis acceptez les paramètres "utilisateur" et "mot de passe" via GET et ne nécessitez pas d'authentification de base. Ici, utilisez php, node, Java, peu importe, analysez votre fichier passwd et comparez les paramètres (utilisateur/pass). S'il existe une correspondance, redirigez-le vers http: // utilisateur: [email protected]/ (cela définira les informations d'identification sur votre navigateur). Sinon, envoyez une réponse 401 (sans en-tête WWW-Authenticate).

0
neiker