web-dev-qa-db-ja.com

CORS:PHP:プリフライトリクエストへの応答が失敗しました。発信元を許可しています

だから私はそこにたくさんのCORS投稿があることを知っています、そして私はそれらに追加しているだけですが、私を助ける答えを持つものを見つけることができません。したがって、angular 4 php apiに依存する4つのアプリケーションを作成しています。ローカルで動作するので問題ありません。app.example.comのアプリを使用してドメインでアプリケーションを破棄した瞬間、 api.example.comのAPIでは、次のエラーが発生するため、ログインを通過できません。

XMLHttpRequestが読み込めません http://api.example.com/Account/Login 。プリフライト要求への応答がアクセス制御チェックに合格しません:要求されたリソースに「Access-Control-Allow-Origin」ヘッダーがありません。したがって、オリジン ' http://app.example.com 'はアクセスを許可されません。

私のphpコードは次のようになります:

$http_Origin = $_SERVER['HTTP_Origin'];

$allowed_domains = array(
    'http://example.com',
    'https://example.com',
    'http://app.example.com',
    'https://app.example.com',
    'http://www.example.com',
    'https://www.example.com'
);

if (in_array(strtolower($http_Origin), $allowed_domains))
{  
    // header("Access-Control-Allow-Origin: *");
    header("Access-Control-Allow-Origin: $http_Origin");
    header('Access-Control-Allow-Credentials: true');
    header('Access-Control-Max-Age: 86400');
}

// Access-Control headers are received during OPTIONS requests
if ($_SERVER['REQUEST_METHOD'] == 'OPTIONS') {
        header("Access-Control-Allow-Methods: GET, POST, OPTIONS");
        header("Access-Control-Allow-Headers: Authorization, Content-Type,Accept, Origin");
    exit(0);
}

私のAngular投稿は次のようになります:

public login(login: Login): Observable<LoginResponse> {
    let headers = new Headers();
    headers.append('Content-Type', 'application/x-www-form-urlencoded');
    headers.append('Authorization', 'Basic ' + btoa(login.Username + ':' + login.Password));
    return  this.http.post(this.apiBaseUrl + '/Account/Login', "grant_type=client_credentials", { headers: headers })
        .map(response => {
            // code
        });
}

CORSを気にしないpostmanを介してリクエストを実行すると、次のようになります。

{ "error": "invalid_client", "error_description": "Client credentials were not found in the headers or body" }

Originを「*」に設定して、それが問題の核心であるかどうかをテストして確認しましたが、同じように失敗します。

Edit以下の情報から更新するだけです。ヘッダーの大文字と小文字を変更しても効果はなく、ifステートメントからコードを引き出しても効果はありませんでした。

ライブアプリにローカルapiに移動するように指示してphpをデバッグしましたが、phpは期待どおりに動作しています。ヘッダーを設定し、それを各ifステートメントにします。

エディットテイク2私はこれについて実際にいくつかのヘルプを使用できます。本当に感謝しています。

Edit take 3phpではなく.htaccessにすべてのヘッダーを設定すると、通します。しかし、私は今、postmanを使用すると常に発生する上記のエラーに悩まされていますが、実際のサイトを使用しているときです。

{"error":"invalid_client","error_description":"Client credentials were not found in the headers or body"}

私の応答ヘッダーはそうです

Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:authorization, content-type, accept, Origin
Access-Control-Allow-Methods:GET, POST, OPTIONS
Access-Control-Allow-Origin:*

それが機能するようになったら、*から私のドメインのみに変更します。しかし、今のところは*のままにしておきます。

リクエストに応じて私のヘッダー

Headers for failed request

8
Nieminen

OK私は最近同様の問題を抱えており、.htaccessを使用せずにバックエンド側でのみすべてを解決しました。

ブラウザがクロスサーバーリクエストを送信するとき、ブラウザはまずOPTIONSリクエストを送信して、それが有効であり、「実際の」リクエストを送信できることを確認します。 OPTIONSから適切かつ有効な応答を受け取った後、それだけが「実際の」要求を送信します。

次に、バックエンドでの両方のリクエストについて、適切なヘッダーを返すようにする必要があります:content-type、allow-Origin、allow-headersなど...

バックエンドのOPTIONSリクエストで、アプリが完全なフローを継続するのではなく、アプリがヘッダーとレスポンスを返すことを確認してください。

「実際の」リクエストでは、適切なヘッダーと通常の応答本文を返す必要があります。

例:

    //The Response object
    $res = $app->response;

    $res->headers->set('Content-Type', 'application/json');
    $res->headers->set('Access-Control-Allow-Origin', 'http://example.com');
    $res->headers->set('Access-Control-Allow-Credentials', 'true');
    $res->headers->set('Access-Control-Max-Age', '60');
    $res->headers->set('Access-Control-Allow-Headers', 'AccountKey,x-requested-with, Content-Type, Origin, authorization, accept, client-security-token, Host, date, cookie, cookie2');
    $res->headers->set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');

    if ( ! $req->isOptions()) {
        // this continues the normal flow of the app, and will return the proper body
        $this->next->call();
    } else {
        //stops the app, and sends the response
        return $res;
    }

覚えておくべきこと:

  • 使用している場合: "Access-Control-Allow-Credentials" = true "Access-Control-Allow-Origin"が "*"ではないことを確認してください。適切なドメインで設定する必要があります! (ここで大量の血がこぼれた:/)

  • 「Access-Control-Allow-Headers」で取得する許可されたヘッダーを定義します。定義しない場合、リクエストは失敗します

  • 「Authorization:Bearer」を使用している場合、「Access-Control-Allow-Headers」にも「Authorization」が含まれている必要があります。含まれていない場合、リクエストは失敗します
6
Tzook Bar Noy

以下にphpを追加して、問題を解決しました。

header("Access-Control-Allow-Origin: *");

header("Access-Control-Allow-Headers: Content-Type, Origin");
3
Piyush

同様の問題がありました

開発環境:NginXプロキシの背後にあるApache Webサーバー

私のアプリは、次の名前で構成された私のApacheサーバーの仮想ホストにあります:appname.devdomain.com

Webアプリの内部にアクセスするときに、プロキシを経由していませんでした:appname.devdomain.comというURLを使用していました

私はこの方法で問題ありませんでした。

しかし、パブリックurl:appname.prddomain.comを使用して外部にアクセスすると、ロードされ、ログイン後にシステムにアクセスし、テンプレートといくつかのセッションコンテンツをロードします。次に、クライアントによって非同期呼び出しが行われる場合chromeコンソールに次のメッセージが表示されます:

"Access to XMLHttpRequest at 'http://appname.devdomain.com/miAdminPanel.php' from Origin 'http://appname.prddomain.com' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request."

これをテストするために2つのタブを開きました

最初のタブは、url:appname.devdomain.comを使用してWebにアクセスし、XMLHttpRequestを作成しました-> OK

2番目のタブは、URL appname.prddomain.comを使用してWebにアクセスし、上記のXMLHttpRequest-> CORSエラーメッセージを作成しました。

したがって、Nginxプロキシ構成を変更した後:

server {
    listen      80;
    server_name appname.prddomain.com;

    # SSL log files ###
    access_log      /path/to/acces-log.log;
    error_log       /path/to/error-log.log;

location / {
    proxy_pass  http://appname.devdomain.com;
    proxy_set_header X-Forwarded-Host $Host;
    proxy_set_header X-Forwarded-Server $Host;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

これは基本的に、外部リクエストを内部リクエストとして扱うようにプロキシに指示します。

0
1rx