web-dev-qa-db-fra.com

Set-Cookie dans l'en-tête HTTP est ignoré avec AngularJS

Je travaille sur une application basée sur AngularJS côté client et sur Java pour mon API (Tomcat + Jersey pour WS) côté serveur.

Certains chemins de mon API sont limités. Si l'utilisateur n'a pas de session, l'état de la réponse renvoyé est 401. Du côté client, les états 401 http sont interceptés pour rediriger l'utilisateur vers la page de connexion.

Une fois l'utilisateur authentifié, je crée une session côté serveur.

httpRequest.getSession (true);
 Set-Cookie: JSESSIONID = XXXXXXXXXXXXXXXXXXXXX; Domain = localhost; Path =/api /; HttpOnly 

Le problème est que le cookie n'est jamais placé du côté client. Lorsque j'inspecte le cookie du domaine localhost, celui-ci est vide. Par conséquent, les demandes suivantes n'ont pas ce cookie dans leur en-tête et le client ne peut toujours pas accéder au chemin d'accès restreint de mon API.

Le client et le serveur sont sur le même domaine mais ils n'ont pas le même chemin et le même numéro de port:

Client : http://localhost:8000/app/index.html

Serveur: http://localhost:8080/api/restricted/

Informations complémentaires: CORS est activé des deux côtés:

"Méthodes d'accès-de contrôle-autorisation", "GET, POST, OPTIONS" 
 "Origine de contrôle d'accès", "*" 
 "Informations d'authentification de contrôle d'accès", vrai

Une idée pour que le cookie Set fonctionne correctement? Est-ce un problème lié à AngularJS?

67
Romain Lefrancois

J'ai trouvé un numéro dans AngularJS qui m'aide à avancer.

Il paraît que "Access-Control-Allow-Credentials" : true n'était pas défini du côté client. Instruction $httpProvider.defaults.withCredentials = true a été ignoré.

Je remplace l’appel $ resource par un simple appel $ http avec {withCredentials: true} dans le paramètre config.

21
Romain Lefrancois

J'ai réussi à résoudre un problème très similaire au vôtre. Mon jeu! backend a essayé de définir un cookie de session que je ne pouvais pas attraper Angular ou stocker via un navigateur.

En fait, la solution impliquait un peu de ceci et un peu de cela.

En supposant que vous ayez résolu le problème initial, qui ne peut être résolu qu'en ajoutant un domaine spécifique à Access-Control-Allow-Origin et en supprimant le caractère générique, procédez comme suit:

  1. Vous devez supprimer le HTTP-Only du Set-Cookie en-tête, sinon vous ne pourrez jamais recevoir un cookie "généré" par votre angular
    Cette configuration fonctionnera déjà dans Firefox, mais pas dans Chrome

  2. Pour que cela fonctionne avec Chrome aussi, vous devez:

    a) envoyez un domaine différent de localhost dans le cookie, en utilisant le domaine pour lequel vos WS sont "hébergés". Vous pouvez même utiliser des jokers comme .domain.com au lieu de ws.domain.com

    b) vous devrez ensuite appeler le domaine que vous avez spécifié dans le cookie, sinon Chrome ne stockera pas votre cookie

    [facultatif] Je retirerais ce /api chemin en faveur d'un /


Et cela devrait faire l'affaire.
J'espère avoir été utile

17
domokun

Dans votre demande de publication côté client, veillez à ajouter les éléments suivants:

Pour les requêtes jquery ajax:

$.ajax({
  url: "http://yoururlgoeshere",
  type: "post",
  data: "somedata",
  xhrFields: {
    withCredentials: true
  }
});

Avec le service $ http de Angular:

$http.post("http://yoururlgoeshere", "somedata", {
  withCredentials: true
});
13
Teliov

L'addition HttpOnly signifie que le navigateur ne doit pas laisser les plugins et JavaScript voir le cookie. Ceci est une convention récente pour une navigation plus sûre. Devrait être utilisé pour J_SESSIONID mais peut-être pas ici.

7
Joop Eggen

Vous devez travailler à la fois côté serveur et côté client.

Client

Ensemble $http config withCredentials à true de l’une des manières suivantes:

  1. Par reqûette

    var config = {withCredentials: true};
    $http.post(url, config);
    
  2. Pour toutes les demandes

    angular.module("your_module_name").config(['$httpProvider',
      function($httpProvider) {
        $httpProvider.interceptors.Push(['$q',
          function($q) {
            return {
              request: function(config) {
                config.withCredentials = true;
                return config;
              }
            };
          }
        ]);
      }
    ]);
    

Serveur

Définir l'en-tête de réponse Access-Control-Allow-Credentials à true.

7
Edmond Chui

Je viens de résoudre un problème comme celui-ci.

Je faisais ça et je ne travaillais pas ...:

  $cookies.put('JSESSIONID', response.data);

Les cookies sont enregistrés dans le navigateur, mais lorsque j'ai envoyé une nouvelle demande, tous les cookies ont été envoyés sauf le mien. (mon cookie est JSESSIONID)

alors je regarde dans le chrome inspecteur et j'ai trouvé ceci: My session are the JsessionID

LE PROBLÈME IS C'ÉTAIT PAS LE BON CHEMIN !!!

alors j'ai essayé ceci et mes cookies ont été envoyés. Yay! :

$cookies.put('JSESSIONID', response.data, {'path':'/'});

Je ne sais pas si c'est votre cas, mais cela a fonctionné pour moi.

cordialement!

1