Як додати Access-Control-Allow-Origin у NGINX?


158

Як встановити заголовок Access-Control-Allow-Origin, щоб я міг використовувати веб-шрифти з мого субдомену в основному домені?


Примітки:

Ви знайдете приклади цього та інших заголовків для більшості HTTP-серверів у проектах HTML5BP Configs https://github.com/h5bp/server-configs


4
ах нарешті знайдено місце відповіді / {add_header Access-Control-Allow-Origin "*"; }
Кріс Маккі

Відповіді:


182

Nginx має бути скомпільовано за допомогою http://wiki.nginx.org/NginxHttpHeadersModule (за замовчуванням для Ubuntu та деяких інших дистрибутивів Linux). Тоді ви можете це зробити

location ~* \.(eot|ttf|woff|woff2)$ {
    add_header Access-Control-Allow-Origin *;
}

Дотримуйтесь інструкцій , це в разі , якщо ви хочете хочете реалізувати таке ж рішення на апача: stackoverflow.com/questions/11616306 / ...
camilo_u

6
Цей модуль, здається, компілюється за замовчуванням (принаймні, на Ubuntu).
Стів Беннетт

1
також складено за замовчуванням на amazon linux repo
Росс

1
У якому файлі та розташуванні ми повинні розмістити цю директиву про місцезнаходження?
Суміт Арора

1
Це не працює для мене. Nginx 1.10.0, Ubuntu 16.04
Омід Амрей

36

Більш актуальна відповідь:

#
# Wide-open CORS config for nginx
#
location / {
     if ($request_method = 'OPTIONS') {
        add_header 'Access-Control-Allow-Origin' '*';
        #
        # Om nom nom cookies
        #
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        #
        # Custom headers and headers various browsers *should* be OK with but aren't
        #
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
        #
        # Tell client that this pre-flight info is valid for 20 days
        #
        add_header 'Access-Control-Max-Age' 1728000;
        add_header 'Content-Type' 'text/plain charset=UTF-8';
        add_header 'Content-Length' 0;
        return 204;
     }
     if ($request_method = 'POST') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
     }
     if ($request_method = 'GET') {
        add_header 'Access-Control-Allow-Origin' '*';
        add_header 'Access-Control-Allow-Credentials' 'true';
        add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS';
        add_header 'Access-Control-Allow-Headers' 'DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type';
     }
}

джерело: https://michielkalkman.com/snippets/nginx-cors-open-configuration.html

Ви також можете додати Access-Control-Expose-Headers(у тому ж форматі, що і Access-Control-Allow-Headers), щоб викрити власні та / або непрості заголовки до запитів ajax.

Access-Control-Expose-Headers (optional) - The XMLHttpRequest 2 object has a 
getResponseHeader() method that returns the value of a particular response 
header. During a CORS request, the getResponseHeader() method can only access 
simple response headers. Simple response headers are defined as follows:

    Cache-Control
    Content-Language
    Content-Type
    Expires
    Last-Modified
    Pragma
 If you want clients to be able to access other headers, you have to use the
 Access-Control-Expose-Headers header. The value of this header is a comma-
 delimited list of response headers you want to expose to the client.

- http://www.html5rocks.com/en/tutorials/cors/

Налаштування для інших веб-серверів http://enable-cors.org/server.html


1
Будь-який спосіб не повторювати ці рядки для кожного місця? Чи можемо ми поставити його під блок {} сервера?
geoyws

@geoyws (без @ я не отримав повідомлення); ви можете поставити його над розташуванням, це добре :)
Кріс Маккі

тут відсутній заголовок доступу-контролю-
експонування

3
Будь ласка, уникайте використання ifnginx - навіть офіційна інструкція не відволікає його .
aggregate1166877

1
Я хотів би додати, що корисно додати alwaysваріант для всіх, add_headerщоб заголовки були додані також для відповідей, що не мають 200. Так як Nginx 1.7.5: nginx.org/en/docs/http/ngx_http_headers_module.html
Mitar

11

Ось стаття, яку я написав, яка уникає певного дублювання для GET | POST. Це має змусити вас їхати з CORS в Nginx.

nginx контроль доступу дозволяє походження

Ось фрагмент зразка з публікації:

server {
  listen        80;
  server_name   api.test.com;


  location / {

    # Simple requests
    if ($request_method ~* "(GET|POST)") {
      add_header "Access-Control-Allow-Origin"  *;
    }

    # Preflighted requests
    if ($request_method = OPTIONS ) {
      add_header "Access-Control-Allow-Origin"  *;
      add_header "Access-Control-Allow-Methods" "GET, POST, OPTIONS, HEAD";
      add_header "Access-Control-Allow-Headers" "Authorization, Origin, X-Requested-With, Content-Type, Accept";
      return 200;
    }

    ....
    # Handle request
    ....
  }
}

2
Згідно з політикою SF, вам потрібно скопіювати інформацію в пост, а не просто посилатися на неї. Веб-сайти можуть зникнути в будь-який час, що може бути втратою інформації.
Тім

1
Дійсна точка @tim, оновлена ​​для включення коду
gansbrest

Подумайте про використання коду статусу, 204 No contentяк видається більш доцільним.
Слава Фомін II

7

По-перше, дозвольте сказати, що відповідь @hellvinz працює на мене:

location ~* \.(eot|ttf|woff|woff2)$ {
    add_header Access-Control-Allow-Origin *;
}

Однак я вирішив відповісти на це питання окремою відповіддю, оскільки мені вдалося змусити це рішення працювати лише після того, як ще десять годин шукаю рішення.

Здається, що Nginx за замовчуванням не визначає будь-яких (правильних) типів MIME шрифту. Дотримуючись цього навчального матеріалу, я виявив, що можу додати наступне:

application/x-font-ttf           ttc ttf;
application/x-font-otf           otf;
application/font-woff            woff;
application/font-woff2           woff2;
application/vnd.ms-fontobject    eot;

До мого etc/nginx/mime.typesфайлу. Як було зазначено, вищевказане рішення тоді спрацювало.


2
Зазвичай я вказую людям перевірити файл типу mime на H5BP github.com/h5bp/server-configs-nginx/blob/master/mime.types :)
Кріс Маккі

4

Традиційна директива add_header від Nginx не працює з відповідями 4xx. Оскільки ми все ще хочемо додати до них власні заголовки, нам потрібно встановити модуль ngx_headers_more, щоб мати можливість використовувати директиву more_set_headers, яка також працює з відповідями 4xx.

sudo apt-get install nginx-extras

Потім використовуйте more_set_headers у файлі nginx.conf, я вставлю зразок нижче

server {
    listen 80;
    server_name example-site.com;
    root "/home/vagrant/projects/example-site/public";

    index index.html index.htm index.php;

    charset utf-8;

    more_set_headers 'Access-Control-Allow-Origin: $http_origin';
    more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE, HEAD';
    more_set_headers 'Access-Control-Allow-Credentials: true';
    more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept,Authorization';

    location / {
        if ($request_method = 'OPTIONS') {
            more_set_headers 'Access-Control-Allow-Origin: $http_origin';
            more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT, DELETE, HEAD';
            more_set_headers 'Access-Control-Max-Age: 1728000';
            more_set_headers 'Access-Control-Allow-Credentials: true';
            more_set_headers 'Access-Control-Allow-Headers: Origin,Content-Type,Accept,Authorization';
            more_set_headers 'Content-Type: text/plain; charset=UTF-8';
            more_set_headers 'Content-Length: 0';
            return 204;
        }
        try_files $uri $uri/ /index.php?$query_string;
    }

    location = /favicon.ico { access_log off; log_not_found off; }
    location = /robots.txt  { access_log off; log_not_found off; }

    access_log off;
    error_log  /var/log/nginx/example-site.com-error.log error;

    sendfile off;

    client_max_body_size 100m;

    location ~ \.php$ {
        fastcgi_split_path_info ^(.+\.php)(/.+)$;
        fastcgi_pass unix:/var/run/php5-fpm.sock;
        fastcgi_index index.php;
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        fastcgi_intercept_errors off;
        fastcgi_buffer_size 16k;
        fastcgi_buffers 4 16k;
    }

    location ~ /\.ht {
        deny all;
    }
}

1

У деяких випадках потрібно використовувати add_headerдирективи, alwaysщоб охопити всі коди відповідей HTTP.

location / {
    add_header 'Access-Control-Allow-Origin' '*' always;
}

З документації :

Якщо параметр завжди вказаний (1.7.5), поле заголовка буде додано незалежно від коду відповіді.

Додає вказане поле до заголовка відповіді за умови, що код відповіді дорівнює 200, 201 (1.3.10), 204, 206, 301, 302, 303, 304, 307 (1.1.16, 1.0.13) або 308 (1.13 .0). Значення параметра може містити змінні.


0

У моєму випадку, використовуючи Rails 5, єдиним робочим рішенням було додавання rack-corsдорогоцінного каменю. Так:

в / Gemfile

# Gemfile
gem 'rack-cors'

у config / ініціалізаторах / cors.rb

# config/initializers/cors.rb
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'localhost:4200'
    resource '*',
      headers: :any,
      methods: %i(get post put patch delete options head)
  end
end

джерело: https://til.hashrocket.com/posts/4d7f12b213-rails-5-api-and-cors


як це допомагає nginx обслуговувати статичні файли?
Вальф

Я використовував nginx як зворотний проксі для обслуговування програми rails 5. Це конкретний випадок, коли обмеження CORS прийшло не від nginx, а від вихідного Rails App, що стоїть за ним.
user9869932
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.