Zezwalaj na wszystko za pośrednictwem zasad CORS

100

Jak mogę wyłączyć cors? Z jakiegoś powodu zaznaczyłem dozwolone źródła i nagłówki, ale moje żądania Ajax wciąż narzekają, że pochodzenie nie było dozwolone przez moje zasady CORS ...

Kontroler moich aplikacji:

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

trasy:

  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"

Edytować---

Próbowałem też:

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

w application.rb

--edyt 2 ---

Problem polega na tym, że rozszerzenia Chrome mogą nie obsługiwać CORS. Jak mogę pobrać informacje z pominięciem CORS? Jak mam odpowiedzieć na kontrolę przed lotem?

Nonkonformista
źródło
1
Nie „wyłączasz CORS”, ale faktycznie nie masz żadnych zasad? Nie mogę odpowiedzieć na żadną prośbę.
Nonkonformista
1
Czy używasz tego na hoście lokalnym?
Dzung Nguyen

Odpowiedzi:

154

Mam te same wymagania co do publicznego API, dla którego użyłem rails-api.

Ustawiłem również nagłówek w filtrze przed. To wygląda tak:

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'

Wygląda na to, że przegapiłeś nagłówek Access-Control-Request-Method.

matowy
źródło
To jest dziwne. Czy mógłbyś podać więcej informacji na temat otrzymanego błędu?
matteo
github.com/cleor41/Cors-Rails4-API Sprawdź to, jeśli nie wiesz, gdzie to jeszcze umieścić.
CleoR
8
Metoda-kontroli-żądania-dostępu jest ustawiona w żądaniu, a nie w odpowiedzi. developer.mozilla.org/en-US/docs/Web/HTTP/ ...
kuboon
19

Przyjrzyj się oprogramowaniu pośredniczącemu rack-cors . Będzie obsługiwać nagłówki CORS w konfigurowalny sposób.

Jef
źródło
2
Używaliśmy rack-cors od miesięcy i do tej pory nie napotkaliśmy żadnego problemu. Czy na pewno problem nie występuje po stronie klienta?
Jef,
1
Myślę, że problem polega na tym, że rozszerzenia Chrome nie obsługują CORS, więc może pochodzenie jest zerowe. Jak mogę całkowicie wyłączyć CORS i odpowiedzieć na każde żądanie, w tym żądania o zerowych źródłach?
Nonkonformista
Z jakiego rozszerzenia Chrome korzystasz?
Jef
1
Piszę rozszerzenie Chrome, które musi komunikować się z moim zapleczem Railsów.
Nonkonformista
12

Po prostu możesz dodać gem rack-cors https://rubygems.org/gems/rack-cors/versions/0.4.0

1. krok: dodaj klejnot do swojego Gemfile:

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

a następnie zapisz i uruchom bundle install

Drugi krok: zaktualizuj plik config / application.rb, dodając to:

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

Aby uzyskać więcej informacji, przejdź do https://github.com/cyu/rack-cors Specailly, jeśli nie używasz szyn 5.

Abdallah Okasha
źródło
Dla mnie to .insert_before 0było ważne. Wcześniej korzystałem config.middleware.usei działało to tylko do momentu, gdy chciałem zezwolić na CORS dla mojego publickatalogu.
Tsunamis
5

Miałem problemy, zwłaszcza z Chrome. To, co zrobiłeś, wygląda zasadniczo tak, jak ja w mojej aplikacji. Jedyną różnicą jest to, że odpowiadam poprawnymi nazwami hostów w nagłówkach Origin CORS, a nie symbolem wieloznacznym. Wydaje mi się, że Chrome jest w tym wybredny.

Przełączanie się między programowaniem a produkcją jest uciążliwe, więc napisałem tę małą funkcję, która pomaga mi w trybie programistycznym, a także w trybie produkcyjnym. Wszystkie poniższe rzeczy dzieją się w moim, application_controller.rbchyba że zaznaczono inaczej, to może nie jest najlepsze rozwiązanie, ale dla mnie też nie działały rack-cors , nie pamiętam dlaczego.

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

A potem mam w sobie tę małą rzecz, application_controller.rbponieważ moja witryna wymaga logowania:

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

W moim routes.rbmam też to:

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

a ta metoda wygląda tak:

def empty
  render :nothing => true
end
Christoph Eicke
źródło
1
Żeby zamknąć krąg. Ten cały bałagan CORS ma miejsce tylko wtedy, gdy trafisz na zaplecze produkcyjne z aplikacji localhost, prawda? Nic z tego się nie wydarzy, gdy wszystko będzie w produkcji?
Sebastialonso
2
Tylko wtedy, gdy zaplecze i aplikacja internetowa są hostowane pod tym samym adresem URL. Jeśli są hostowane całkowicie pod dwoma różnymi adresami URL, stanie się to również w wersji produkcyjnej.
Christoph Eicke,
3

Miałem podobny problem wcześniej, gdzie okazało się, że przyczyną był przeglądarka internetowa (w moim przypadku Chrome).

Jeśli używasz Chrome, spróbuj go uruchomić, więc:

Dla Windowsa:

1) Utwórz skrót do Chrome na pulpicie. Kliknij skrót prawym przyciskiem myszy i wybierz Właściwości, a następnie przejdź do zakładki „Skrót”.

2) W polu „Target” dodaj: –args –disable-web-security

W przypadku komputerów Mac otwórz okno terminala i uruchom je z wiersza poleceń: otwórz ~ / Applications / Google \ Chrome.app/ –args –disable-web-security

Powyższe informacje z:

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

PropertyWebBuilder
źródło
Dlaczego głosowanie odrzucono? Miałem sytuację podobną do tej opisanej w pytaniu, która została rozwiązana przez uruchomienie przeglądarki Chrome z wyłączonymi zabezpieczeniami sieciowymi. Problem występuje podczas lokalnego uruchamiania serwera deweloperskiego. Oczywiście nie zostawiłbyś Chrome działającego z wyłączonymi zabezpieczeniami internetowymi.
PropertyWebBuilder
nie powinno to być głosowane w głosowaniu, ponieważ poprawnie wyjaśnia sytuację :)
Dzung Nguyen
4
Nie głosowałem przeciw, ale z odpowiedzi nie wynika, że ​​jest to rozwiązanie wyłącznie dla celów rozwojowych. Chociaż może to rozwiązać problem lokalnie, nie można oczekiwać, że użytkownicy odwiedzający witrynę lub użytkownicy rozszerzeń będą to robić. Więc wyjaśniłbym to w odpowiedzi.
nathanvda
1
Tutaj też nie ma głosowania, ale było tak, że pierwsza instancja chrome uruchomiona z daną flagą powodowała, że ​​wszystkie inne instancje działały w ten sam sposób. Coś, na co należy bardzo uważać. Zbyt łatwo jest o tym zapomnieć i zaimprowizować surfowanie.
dc5,
2

Właśnie napotkałem ten problem w mojej aplikacji szynowej w produkcji. Wiele odpowiedzi tutaj dało mi wskazówki i pomogło mi w końcu dojść do odpowiedzi, która działała dobrze.

Używam Nginx i wystarczyło zmodyfikować plik my_app.conf (gdzie my_app to nazwa twojej aplikacji). Możesz znaleźć ten plik w/etc/nginx/conf.d

Jeśli jeszcze tego nie location / {}zrobiłeś, możesz po prostu dodać go pod server {}, a następnie dodać add_header 'Access-Control-Allow-Origin' '*';pod location / {}.

Ostateczny format powinien wyglądać mniej więcej tak:

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

    location / {
        add_header 'Access-Control-Allow-Origin' '*';
    }
}
HB
źródło
-2

Wypróbuj konfigurację w /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
Leonardo Ostan
źródło
Zapomniałeś wspomnieć, że deweloper powinien dodać `` rack-cors '' w Gemfile
Gabriel Lidenor