Дозволити що-небудь за допомогою політики CORS


100

Як я можу відключити диски? Чомусь я підкреслив дозволене походження та заголовки, але мої запити від ajax досі скаржаться на те, що походження не було дозволене моєю політикою CORS ....

Мій контролер програм:

class ApplicationController < ActionController::Base
  protect_from_forgery
  before_filter :current_user, :cors_preflight_check
  after_filter :cors_set_access_control_headers

# For all responses in this controller, return the CORS access control headers.

def cors_set_access_control_headers
  headers['Access-Control-Allow-Origin'] = '*'
  headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
  headers['Access-Control-Allow-Headers'] = '*'
  headers['Access-Control-Max-Age'] = "1728000"
end

# If this is a preflight OPTIONS request, then short-circuit the
# request, return only the necessary headers and return an empty
# text/plain.

def cors_preflight_check
  if request.method == :options
    headers['Access-Control-Allow-Origin'] = '*'
    headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
    headers['Access-Control-Allow-Headers'] = '*'
    headers['Access-Control-Max-Age'] = '1728000'
    render :text => '', :content_type => 'text/plain'
  end
end
  private
  # get the user currently logged in
  def current_user
    @current_user ||= User.find(session[:user_id]) if session[:user_id]
  end
  helper_method :current_user

end

маршрути:

  match "*all" => "application#cors_preflight_check", :constraints => { :method => "OPTIONS" }
  match "/alert" => "alerts#create"
  match "/alerts" => "alerts#get"
  match "/login" => "sessions#create"
  match "/logout" => "sessions#destroy"
  match "/register" => "users#create"

Редагувати ---

Я також спробував:

   config.middleware.use Rack::Cors do
      allow do
        origins '*'
        resource '*', 
            :headers => :any, 
            :methods => [:get, :post, :delete, :put, :options]
      end
    end

у застосуванні.rb

--edit 2 ---

Проблема полягає в тому, що розширення Chrome можуть не підтримувати CORS. Як я можу отримати інформацію в обхід CORS? Як я повинен відповісти на перевірку перед польотом?


1
Не "відключати CORS", але фактично не мають політики? Я не можу відповісти ні на який запит.
нонконформіст

1
Чи використовуєте ви це у localhost?
Дзунг Нгуен

Відповіді:


154

У вас такі ж вимоги щодо публічного API, для якого я використовував rails-api.

Я також встановив заголовок у фільтрі до. Це виглядає приблизно так:

headers['Access-Control-Allow-Origin'] = '*'
headers['Access-Control-Allow-Methods'] = 'POST, PUT, DELETE, GET, OPTIONS'
headers['Access-Control-Request-Method'] = '*'
headers['Access-Control-Allow-Headers'] = 'Origin, X-Requested-With, Content-Type, Accept, Authorization'

Здається, ви пропустили заголовок Access-Control-Request-Method.


Це дивно. Чи можете ви надати більше інформації про помилку, яку ви отримали?
matteo

github.com/cleor41/Cors-Rails4-API Перевірте це, якщо ви не знаєте, де його ще розмістити.
CleoR

8
Метод доступу-контролю-запиту встановлюється у запиті, а не у відповідь. developer.mozilla.org/en-US/docs/Web/HTTP/…
kuboon

19

Погляньте на проміжне програмне забезпечення rack-cors . Він буде обробляти заголовки CORS у налаштованому порядку.


2
Ми використовували стійки-корки місяцями і досі не сприяли жодній проблемі. Ви впевнені, що проблема не існує на стороні клієнта?
Jef

1
Я думаю, що проблема полягає в тому, що розширення Chrome не підтримують CORS, тому, можливо, Origin - Null. Як я можу повністю відключити CORS і відповісти на будь-який запит, включаючи запити з нульовим походженням?
нонконформіст

Яке розширення Chrome ви використовуєте?
Джеф

1
Я пишу хромоване розширення, яке потребує зв’язку з моєю програмою Rails.
Нонконформіст

12

Просто ви можете додати rack-cors gem https://rubygems.org/gems/rack-cors/versions/0.4.0

1-й крок: додайте дорогоцінний камінь у свій Gemfile:

gem 'rack-cors', :require => 'rack/cors'

а потім збережіть і запустіть bundle install

Другий крок: оновіть файл config / application.rb, додавши це:

config.middleware.insert_before 0, Rack::Cors do
      allow do
        origins '*'
        resource '*', :headers => :any, :methods => [:get, :post, :options]
      end
    end

Більш детальну інформацію можна отримати на https://github.com/cyu/rack-cors Specailly, якщо ви не використовуєте рейки 5.


Для мене це .insert_before 0було важливим. До цього я config.middleware.useпрацював і працював лише до тих пір, поки не захотів дозволити CORS для свого publicкаталогу.
Цунамі

5

У мене виникли проблеми, особливо з Chrome. Те, що ви зробили, по суті схоже на те, що я зробив у своїй заяві. Єдина відмінність полягає в тому, що я відповідаю правильними іменами хостів у своїх заголовках Origin CORS, а не підстановкою. Мені здається, що Chrome до цього прискіпливий.

Переключення між розвитком і виробництвом - це біль, тому я написав цю маленьку функцію, яка допомагає мені в режимі розвитку, а також у виробничому режимі. Усі наступні речі трапляються в моєму application_controller.rbвипадку, якщо не зазначено інше, це може бути не найкращим рішенням, але рейкові коси для мене теж не спрацювали, я не пам'ятаю чому.

def add_cors_headers
  origin = request.headers["Origin"]
  unless (not origin.nil?) and (origin == "http://localhost" or origin.starts_with? "http://localhost:")
    origin = "https://your.production-site.org"
  end
  headers['Access-Control-Allow-Origin'] = origin
  headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS, PUT, DELETE'
  allow_headers = request.headers["Access-Control-Request-Headers"]
  if allow_headers.nil?
    #shouldn't happen, but better be safe
    allow_headers = 'Origin, Authorization, Accept, Content-Type'
  end
  headers['Access-Control-Allow-Headers'] = allow_headers
  headers['Access-Control-Allow-Credentials'] = 'true'
  headers['Access-Control-Max-Age'] = '1728000'
end

І тоді у мене є ця дрібниця, application_controller.rbоскільки для мого сайту потрібен логін:

before_filter :add_cors_headers
before_filter {authenticate_user! unless request.method == "OPTIONS"}

У своєму routes.rbмене теж є таке:

match '*path', :controller => 'application', :action => 'empty', :constraints => {:method => "OPTIONS"}

і такий спосіб виглядає приблизно так:

def empty
  render :nothing => true
end

1
Тільки щоб закрити коло. Весь цей безлад CORS трапляється лише тоді, коли ви потрапляєте на задній план виробництва з програми localhost, правда? Нічого цього не станеться, коли все буде у виробництві?
Себастіалонсо

2
Тільки якщо сервіс бекенда та webapp розміщений під однією URL-адресою. Якщо вони розміщуються за двома різними URL-адресами цілком, то це станеться і у виробництві.
Крістоф Ейке

3

У мене була аналогічна проблема раніше, де виявилося, що веб-браузер (хром у моєму випадку), в чому це було.

Якщо ви використовуєте хром, спробуйте запустити його так:

Для Windows:

1) Створіть ярлик до Chrome на робочому столі. Клацніть правою кнопкою миші на ярлик і виберіть "Властивості", а потім перейдіть на вкладку "Ярлик".

2) У полі «Ціль» додайте наступне: –аргі –захистити-захист веб-сторінок

Для Mac відкрийте вікно терміналу та запустіть це з командного рядка: відкрийте ~ / Applications / Google \ Chrome.app/ –args –disable-web-security

Вище інформація:

http://documentumcookbook.wordpress.com/2012/03/13/disable-cross-domain-javascript-security-in-chrome-for-development/


Чому це було проголосовано? У мене виникла ситуація, подібна до описаної у запитанні, яке було вирішено за допомогою хромування з відключеною веб-безпекою. Проблема виникає при локальному запуску сервера розробки. Очевидно, ви не залишатимете хром завжди працювати з відключеною веб-безпекою.
PropertyWebBuilder

за це не слід голосувати, оскільки він правильно пояснює ситуацію :)
Dzung Nguyen

4
Я не займався голосуванням, але з відповіді не видно це рішення лише для цілей розвитку. Хоча це може вирішити проблему на локальному рівні, не можна очікувати, що ваші веб-відвідувачі / користувачі розширень будуть це робити. Тож я б уточнив це у відповіді.
nathanvda

1
Тут також немає жодного проголосування, але раніше було те, що перший екземпляр хромованого запуску із заданим прапором змусив усі інші екземпляри працювати так само. Щось дуже обережно. Все занадто просто забути і зробити деякий імпровізований серфінг.
dc5

2

Щойно зіткнувся з цим питанням у моїй застосуванні рейок у виробництві. Багато відповідей тут дало мені підказки і допомогло мені нарешті дійти до відповіді, яка добре працювала для мене.

Я запускаю Nginx, і це було досить просто, щоб просто змінити файл my_app.conf (де my_app - ваше ім'я програми). Ви можете знайти цей файл у/etc/nginx/conf.d

Якщо у вас ще немає, location / {}ви можете просто додати його під server {}, а потім додати add_header 'Access-Control-Allow-Origin' '*';під location / {}.

Остаточний формат повинен виглядати приблизно так:

server {
    server_name ...;
    listen ...;
    root ...;

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

-2

Спробуйте налаштування за адресою /config/application.rb:

config.middleware.insert_before 0, "Rack::Cors" do
  allow do
    origins '*'
    resource '*', :headers => :any, :methods => [:get, :post, :options, :delete, :put, :patch], credentials: true
  end
end

Ви забули згадати, що розробник повинен додати «стійки-корки» в Gemfile
Габріель Лідендор
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.