Конфигурация nginx для включения CORS с сопоставлением происхождения - PullRequest
0 голосов
/ 22 января 2019

Я пытался использовать очень популярную конфигурацию для nginx, которая включает CORS и поддерживает сопоставление происхождения с помощью регулярных выражений.

Вот моя конфигурация:

server {
    listen 80 default_server;
    root /var/www;

    location / {
        if ($http_origin ~ '^http://(www\.)?example.com$') {
            add_header Access-Control-Allow-Origin "$http_origin";
        }

        # Handling preflight requests
        if ($request_method = OPTIONS) {
            add_header Content-Type text/plain;
            add_header Content-Length 0;
            return 204;
        }
    }
}

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

Согласно официальной статье If Is Evil , это ожидаемое поведение для nginx.

Если If Is Evil как мне включить CORS в nginx?Или, может быть, есть способ как-то преодолеть это ограничение?

Ответы [ 3 ]

0 голосов
/ 22 января 2019

Единственное решение Я обнаружил, что до сих пор это был хак, чтобы использовать переменную для агрегирования нескольких условий, а затем сопоставить ее только с одним оператором if, поэтому дублируя некоторые директивы:

server {
    listen 80 default_server;
    root /var/www;

    location / {
        set $cors '';
        set $cors_allowed_methods 'OPTIONS, HEAD, GET';

        if ($http_origin ~ '^https?://(www\.)?example.com$') {
            set $cors 'origin_matched';
        }

        # Preflight requests
        if ($request_method = OPTIONS) {
            set $cors '${cors} & preflight';
        }

        if ($cors = 'origin_matched') {
            add_header Access-Control-Allow-Origin $http_origin;
        }

        if ($cors = 'origin_matched & preflight') {
            add_header Access-Control-Allow-Origin $http_origin always;
            add_header Access-Control-Allow-Methods $cors_allowed_methods;
            add_header Content-Type text/plain;
            add_header Content-Length 0;
            return 204;
        }
    }
}
0 голосов
/ 22 января 2019

Не вдаваясь в детали вашей настройки nginx, она все равно не сработает, потому что возвращаемые вами заголовки CORS неверны ...

В частности:

  • Для предварительных запросов (OPTIONS) единственными значимыми заголовками ответа CORS являются следующие: Access-Control-Allow Origin, (обязательно) , Access-Control-Allow Credentials (необязательно), Access-Control-Allow-Methods, (обязательно) , Access-Control-Allow-Headers, (обязательно) и Access-Control-Max-Age, (необязательно). Все остальные игнорируются.

  • Для обычных (не OPTIONS) запросов единственными значимыми заголовками ответа CORS являются следующие: Access-Control-Allow Origin (обязательно) , Access-Control-Allow Credentials (необязательно) и Access-Control-Expose-Headers (необязательно) ). Все остальные игнорируются.

Обратите внимание на те обязательные заголовки для запросов перед полетом - в настоящее время вы пропускаете только два из них ... Кроме того, обратите внимание, что вам не нужно возвращать Access-Control-Allow-Methods для запроса без OPTIONS - он не 'действителен', поэтому будет игнорироваться.

Что касается вашей конкретной проблемы с nginx, я думаю, @ Слава Фомин II имеет правильный ответ ...

0 голосов
/ 22 января 2019

Вы можете попробовать использовать map istead первого if блока:

map $http_origin $allow_origin {
    ~^http://(www\.)?example.com$ $http_origin;
}
map $http_origin $allow_methods {
    ~^http://(www\.)?example.com$ "OPTIONS, HEAD, GET";
}

server {
    listen 80 default_server;
    root /var/www;

    location / {
        add_header Access-Control-Allow-Origin $allow_origin;
        add_header Access-Control-Allow-Methods $allow_methods;

        # Handling preflight requests
        if ($request_method = OPTIONS) {
            add_header Content-Type text/plain;
            add_header Content-Length 0;
            return 204;
        }
    }
}

nginx откажется добавлять пустые заголовки HTTP, поэтому они будут добавлены, только если заголовок Originприсутствует в запросе и соответствует этому регулярному выражению.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...