Autoriser quoi que ce soit via la politique CORS

100

Comment puis-je désactiver les cors? Pour une raison quelconque, j'ai joker les origines et les en-têtes autorisés, mais mes demandes ajax se plaignent toujours que l'origine n'était pas autorisée par ma politique CORS ....

Mon contrôleur d'applications:

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

itinéraires:

  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"

Éditer---

J'ai aussi essayé:

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

dans application.rb

--edit 2 ---

Le problème est que les extensions Chrome peuvent ne pas prendre en charge CORS, je pense. Comment puis-je récupérer des informations en contournant CORS? Comment dois-je répondre à la vérification avant vol?

Non-conformiste
la source
1
Pas "désactiver CORS" mais effectivement pas de politique? Je n'arrive pas à répondre à aucune demande.
Non
1
L'utilisez-vous sur localhost?
Dzung Nguyen

Réponses:

154

J'ai vos mêmes exigences sur une API publique pour laquelle j'ai utilisé rails-api.

J'ai également défini l'en-tête dans un filtre avant. Cela ressemble à ceci:

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'

Il semble que vous ayez manqué l'en-tête Access-Control-Request-Method.

matteo
la source
C'est étrange. Pourriez-vous fournir plus d'informations sur l'erreur que vous obtenez?
matteo
github.com/cleor41/Cors-Rails4-API Vérifiez ceci si vous ne savez pas où le mettre encore.
CleoR
8
Access-Control-Request-Method est défini dans la demande et non en réponse. developer.mozilla.org/en-US/docs/Web/HTTP/…
kuboon
19

Jetez un œil au middleware rack-cors . Il gérera les en-têtes CORS de manière configurable.

Jef
la source
2
Nous utilisons des rack-cors depuis des mois et n'avons rencontré aucun problème jusqu'à présent. Êtes-vous sûr que le problème ne réside pas du côté client?
Jef
1
Je pense que le problème est que les extensions Chrome ne prennent pas en charge CORS, alors peut-être que l'origine est nulle. Comment puis-je désactiver complètement CORS et répondre à toute demande, y compris les demandes d'origine Null?
Non
Quelle extension Chrome utilisez-vous?
Jef
1
J'écris une extension Chrome qui doit communiquer avec mon backend Rails.
Nonconformist
12

Vous pouvez simplement ajouter des gemmes rack-cors https://rubygems.org/gems/rack-cors/versions/0.4.0

1ère étape: ajoutez une gemme à votre Gemfile:

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

puis enregistrez et exécutez bundle install

2ème étape: mettez à jour votre fichier config / application.rb en ajoutant ceci:

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

pour plus de détails, vous pouvez aller sur https://github.com/cyu/rack-cors Specailly si vous n'utilisez pas de rails 5.

Abdallah Okasha
la source
Pour moi, .insert_before 0c'était important. Avant, j'utilisais config.middleware.useet cela ne fonctionnait que jusqu'à ce que je souhaite autoriser CORS pour mon publicrépertoire.
Tsunamis
5

J'ai eu des problèmes, en particulier avec Chrome également. Ce que vous avez fait ressemble essentiellement à ce que j'ai fait dans ma candidature. La seule différence est que je réponds avec un nom d'hôte correct dans mes en-têtes Origin CORS et non un caractère générique. Il me semble que Chrome est difficile avec cela.

Basculer entre le développement et la production est pénible, j'ai donc écrit cette petite fonction qui m'aide en mode développement et aussi en mode production. Toutes les choses suivantes se produisent dans mon, application_controller.rbsauf indication contraire, ce n'est peut-être pas la meilleure solution, mais les cors de rack ne fonctionnaient pas non plus pour moi, je ne me souviens pas pourquoi.

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

Et puis j'ai ce petit truc dans mon application_controller.rbcar mon site nécessite un login:

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

Dans mon routes.rbj'ai aussi cette chose:

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

et cette méthode ressemble à ceci:

def empty
  render :nothing => true
end
Christoph Eicke
la source
1
Juste pour fermer le cercle. Tout ce désordre CORS ne se produit que lorsque vous accédez à votre back-end de production à partir d'une application localhost, non? Rien de tout cela n'arrivera quand tout sera en production?
Sebastialonso
2
Uniquement si le backend et l'application Web sont hébergés sous la même URL. S'ils sont entièrement hébergés sous deux URL différentes, cela se produira également en production.
Christoph Eicke
3

J'ai déjà eu un problème similaire où il s'est avéré que c'était le navigateur Web (chrome dans mon cas) qui était le problème.

Si vous utilisez Chrome, essayez de le lancer ainsi:

Pour les fenêtres:

1) Créez un raccourci vers Chrome sur votre bureau. Faites un clic droit sur le raccourci et choisissez Propriétés, puis passez à l'onglet «Raccourci».

2) Dans le champ «Cible», ajoutez ce qui suit: –args –disable-web-security

Pour Mac, ouvrez une fenêtre de terminal et exécutez-la à partir de la ligne de commande: ouvrez ~ / Applications / Google \ Chrome.app/ –args –disable-web-security

Ci-dessus les informations de:

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

PropertyWebBuilder
la source
Pourquoi cela a-t-il été rejeté? J'ai eu une situation similaire à celle décrite dans la question qui a été résolue en exécutant Chrome avec la sécurité Web désactivée. Le problème se produit lorsque vous exécutez un serveur de développement localement. De toute évidence, vous ne laisseriez pas Chrome fonctionner avec la sécurité Web toujours désactivée.
PropertyWebBuilder
cela ne devrait pas être rejeté car il explique correctement la situation :)
Dzung Nguyen
4
Je n'ai pas voté contre, mais d'après la réponse, il n'est pas clair qu'il s'agit d'une solution uniquement à des fins de développement. Bien que cela puisse résoudre le problème localement, on ne peut pas s'attendre à ce que vos visiteurs Web / utilisateurs d'extension le fassent. Je voudrais donc clarifier cela dans la réponse.
nathanvda
1
Pas de vote non plus ici non plus, mais auparavant, la première instance de chrome exécutée avec un indicateur donné faisait que toutes les autres instances s'exécutaient de la même manière. Quelque chose à être très méfier. C'est trop facile d'oublier et de faire du surf impromptu.
dc5
2

Je viens de rencontrer ce problème dans mon application rails en production. Beaucoup de réponses ici m'ont donné des indices et m'ont aidé à finalement arriver à une réponse qui a bien fonctionné pour moi.

J'utilise Nginx et c'était assez simple de simplement modifier le fichier my_app.conf (où my_app est le nom de votre application). Vous pouvez trouver ce fichier dans/etc/nginx/conf.d

Si vous ne l'avez pas location / {}déjà, vous pouvez simplement l'ajouter sous server {}, puis ajouter add_header 'Access-Control-Allow-Origin' '*';sous location / {}.

Le format final devrait ressembler à ceci:

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

    location / {
        add_header 'Access-Control-Allow-Origin' '*';
    }
}
HB
la source
-2

Essayez la configuration sur /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
la source
Vous avez oublié de mentionner que le développeur devrait ajouter les `` rack-cors '' dans le Gemfile
Gabriel Lidenor