web-dev-qa-db-ja.com

$ http応答Set-Cookieにアクセスできません

私は現在、バックエンドにangularjsフロントエンドを書いていますが、やや一般的な問題に直面しています:

サーバーは応答でCookieを送り返しますが、angular.jsによって完全に無視されます(「Set-Cookie」値を出力することさえできません)。

読んでみた

AngularJSではHTTPヘッダーのSet-Cookieは無視されます

Angularjs $ httpは応答の「Set-Cookie」を理解していないようです

残念ながら、そこですべての解決策を試しましたが、うまくいかないようです。

リクエストを送信しました

(as captured by Chrome Developer Tools)

受信した応答

(as captured by Chrome Developer Tools)

Angular.js(v1.2.10)を使用していますが、これがリクエストの作成に使用したものです

$http.post('/services/api/emailLogin',
           sanitizeCredentials(credentials), 
           {
              withCredentials: true
           }).success(function(data, status, header) {
                console.log(header('Server'));
                console.log(header('Set-Cookie'));
                console.log(header('Access-Control-Allow-Headers'));
                console.log(header('Access-Control-Allow-Methods'));
                console.log(header);
            }).then(
                function(response) {
                    console.log(response);
                    return response.data;
                });

withCredentials=trueは、リクエストを行う前にクライアント側で設定されます。

Access-Control-Allow-Credentials=trueは、応答を返す前にサーバー側で設定されます。

Set-Cookieは、Chrome Developer Toolsからの応答ヘッダーにありますが、印刷は

(code printout)

応答ヘッダーのSet-Cookieのみが出力されていません。なぜこれが起こるのだろうか? withCredentials=trueが実際に設定されていることを確認する方法はありますか(要求ヘッダーに表示されませんでした)。

どんな助けも大歓迎です!

24
Luke

$httpBackend ソースコード:

xhr.onreadystatechange = function() {

  // some code

  if (xhr && xhr.readyState == 4) {
    var responseHeaders = null,
        response = null;

    if(status !== ABORTED) {
      responseHeaders = xhr.getAllResponseHeaders();

      // some code

それは使用しています XMLHttpRequest#getAllResponseHeaders応答ヘッダーを取得します。

少し検索した後、この質問を見つけました: xmlHttp.getResponseHeader + CORSで動作していません

そのため、XHRの仕様では、XHRはSET-COOKIEなので、特にangle.jsとは関係ありません。

http://www.w3.org/TR/XMLHttpRequest/#the-getallresponseheaders%28%29-method

4.7.4 getAllResponseHeaders()メソッド

応答からすべてのヘッダーを返しますフィールド名がSet-CookieまたはSet-Cookie2のヘッダーを除く


代わりに $cookies

別のモジュールなので、スクリプトに追加する必要があります

 <script src="angular.js"></script>
 <script src="angular-cookies.js"></script>

そして、モジュールの依存関係に追加します:

 var app = angular.module('app',['ngCookies']);

次に、次のように使用します。

app.controller('ctrl',  function($scope, $http , $cookies, $timeout){

  $scope.request = function(){

    $http.get('/api').then(function(response){
      $timeout(function(){
        console.log($cookies.session)
      });         
    })
  }
})

私が使う $timeoutなぜなら$cookiesダイジェスト後にのみブラウザのCookieと同期します。

29
Ilan Frumer

あなたは実際にAngularでクッキーを読む必要がありますか、それが設定されてブラウザによるさらなるリクエストで返されれば十分ですか?前者を機能させることはできませんでしたが、非常に似た構成で後者をかなり迅速に機能させることができました。 (特に、@ Ilanが推奨するように$cookiesを使用できませんでした。何も返されませんでした。)

まず最初に、Angular側で$httpProviderを設定して、デフォルトでwithCredentialsを送信します:

app.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.withCredentials = true;
}]);

Angularで行う必要があるのはそれだけです。この時点で、$cookiesを読み取ろうとすると、Cookieを見ることができませんが、保存され、将来のAJAX呼び出しで渡されます。

次に、サーバー上で、Access-Control-Allow-Credentialsヘッダーとともに、CORSで許可されている特定のドメイン(またはドメインのセット)を提供する必要があります。私のバックエンドはFlask in Python with Flask-Restful であり、次のようになります。

import Flask
from flask_restful import Api
app = Flask(__name__)
api = Api(app)
api.decorators = [cors.crossdomain(Origin='http://localhost:8100', credentials=True)]

それだけで十分です。これでAngular(または、むしろブラウザ)がCookieを設定し、将来のリクエストで完全に透過的にそれを返します!

(同じポイントがここにあります: https://stackoverflow.com/a/19384207/2397068 。)

4
Lane Rettig

ヘッダーを読み取れるようにするには、.htaccessファイルを変更する必要があります。

Header set Access-Control-Allow-Headers Content-Type
0
DDT

Angular 1.3.14では動作しません。

同じ問題がありました。私は$ resourceを使用しており、withCredentials:trueと宣言しています。

 var fooRes = $resource('/address/exemple',
    {},
    {
        bar: {
            method: 'POST',
            withCredentials: true,
        }
    }
 );

 fooRes.bar({
     "stuff" : "lorem"
 }).$promise.then(function(){
     //callback
 })

または、ヘッダー「Access-Control-Allow-Credentials」、「true」を設定できます。

これでCookieが保存され、$ cookieを使用して取得できます。

それが役立つことを願っています。

0
hugodutra