CORS: PHP: ответ на запрос preflight не проходит. Я позволяя происхождения

поэтому я знаю, что там много сообщений CORS, и я просто добавляю к ним, но я не могу найти ответов, которые помогут мне. Поэтому я создаю приложение angular 4, которое опирается на мой php api. Работая локально, это нормально, в тот момент, когда я бросаю его на домен с приложением в app.example.com, и api в api.example.com, Я не могу пройти мой логин, потому что я получаю следующую ошибку:

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

мой угловой пост выглядит так:

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

если я запускаю запрос через почтальона, который не беспокоиться Корс, я получаю:

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

Я попытался установить origin на'*' просто проверить и посмотреть, если это было ядро проблемы, и он по-прежнему терпит неудачу таким же образом.

редактировать Просто обновление информации ниже. Изменение кожуха в заголовках не имело никакого эффекта, и вытаскивание кода из их операторов if не имело никакого эффекта.

Я отладил php, сказав моему живому приложению перейти к моему локальному api, и php работает так, как ожидалось. Это установка заголовков и внесение их в каждый из операторов if.

редактировать дубль 2 Мне действительно нужна помощь в этом, если у кого-то есть идеи, я был бы очень признателен.

изменить, взять 3 Если я установлю все заголовки в свой .htaccess, а не мой php, он позволяет мне пройти. Однако теперь я застрял на ошибке, указанной выше, которую я всегда получаю при использовании postman, однако теперь это при использовании фактический сайт.

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

мои заголовки ответов похожи на so

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

2 ответов


OK у меня недавно были подобные проблемы, и я решил все только на стороне бэкэнда с no .реврайт вещи.

когда браузер отправляет кросс-серверные запросы, он сначала отправляет запрос опций, чтобы убедиться, что он действителен, и он может отправить "реальный" запрос. После того, как он получает правильный и действительный ответ от OPTIONS, только тогда он отправляет "реальный" запрос.

теперь для обоих запросов на бэкэнде вам нужно обязательно вернуть правильные заголовки: content-type, allow-origin, allow-headers и т. д...

убедитесь, что в запросе опций на бэкэнде приложение возвращает заголовки и возвращает ответ, не продолжая полный поток приложения.

в" реальном " запросе вы должны вернуть правильные заголовки и тело регулярного ответа.

пример:

    //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" если вы не определите их, запрос не будет выполнен


Я добавил ниже в PHP, и это решило мою проблему.

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

header("Access-Control-Allow-Headers: Content-Type, origin");