Redirection des Rails avec https

je maintiens un site Ruby on Rails et je ne sais pas comment effectuer des redirections vers des URLs relatives en utilisant le protocole https.

je peux créer avec succès une redirection vers une URL relative en utilisant http, par exemple:

redirect_to "/some_directory/"

mais je ne peux pas discerner comment créer une redirection vers une URL en utilisant le protocole https. Je n'ai pu le faire qu'en utilisant des URLS absolues, par exemple:

redirect_to "https://mysite.com/some_directory/"

j'aimerais garder mon code propre, et utiliser des URLs relatives semble être une bonne idée. Quelqu'un sait-il comment y parvenir dans les chemins de fer?

25
demandé sur DigitalRoss 2009-11-02 19:26:07

8 réponses

il est probablement préférable d'utiliser ssl_requirement et de ne pas se soucier de savoir si un lien ou une redirection utilise ou non https. Avec ssl_requirement, vous déclarez quelles actions nécessitent SSL, lesquelles sont capables de SSL et lesquelles sont tenues de ne pas utiliser SSL.

si vous redirigez quelque part en dehors de votre application Rails, alors spécifier le protocole comme Olly suggère fonctionnera.

9
répondu Andy Gaskell 2014-10-15 12:07:18

la méthode ActionController::Base#redirect_to prend un hachage d'options, dont l'un des paramètres est :protocol qui vous permet d'appeler:

redirect_to :protocol => 'https://', 
            :controller => 'some_controller', 
            :action => 'index'

voir la définition de #redirect_to et #url_for pour plus d'informations sur les options.


alternativement, et surtout si SSL doit être utilisé pour toutes vos actions de controller, vous pourriez prendre un plus déclaratif approche avec un before_filter . Dans ApplicationController , vous pouvez définir la méthode suivante:

def redirect_to_https
    redirect_to :protocol => "https://" unless (request.ssl? || request.local?)
end

vous pouvez alors ajouter des filtres dans vos contrôleurs qui ont des actions nécessitant SSL, E. g:

class YourController
    before_filter :redirect_to_https, :only => ["index", "show"]
end

ou, si vous avez besoin de SSL sur l'ensemble de votre application, déclarez le filtre dans ApplicationController :

class ApplicationController
    before_filter :redirect_to_https
end
35
répondu Olly 2013-03-27 13:34:08

si vous voulez que votre demande entière soit servie sur https puis depuis Rails 4.0 la meilleure façon de faire ceci est d'activer force_ssl dans le fichier de configuration comme ceci:

# config/environments/production.rb
Rails.application.configure do
  # [..]

  # Force all access to the app over SSL, use Strict-Transport-Security,
  # and use secure cookies.
  config.force_ssl = true
end

Par défaut, cette option est déjà présente dans config/environments/production.rb dans de nouvelles applications, mais est commenté.

comme le dit le commentaire, cela ne redirigera pas seulement vers https, mais Strict-Transport-Security en-tête ( HSTS ) et s'assure que le drapeau sécurisé est placé sur tous les cookies. Ces deux mesures augmentent la sécurité de votre application sans inconvénients majeurs. Il utilise ActionDispatch:SSL .

les paramètres d'expiration HSTS sont définis à un an par défaut et n'inclut pas les sous-domaines, ce qui est probablement bien pour la plupart des applications. Vous pouvez le configurer avec l'option hsts :

config.hsts = {
  expires: 1.month.to_i,
  subdomains: false,
}

si vous utilisez Rails 3 (>=3.1) ou si vous ne voulez pas utiliser https pour toute l'application, alors vous pouvez utiliser la méthode force_ssl dans un contrôleur:

class SecureController < ApplicationController
  force_ssl
end

C'est tout. Vous pouvez le régler par controller, ou dans votre ApplicationController . Vous pouvez forcer https conditionnellement en utilisant les options familières if ou unless ; par exemple:

# Only when we're not in development or tests
force_ssl unless: -> { Rails.env.in? ['development', 'test'] }
27
répondu Martin Tournoij 2017-01-13 12:51:16

si vous voulez contrôler globalement le protocole des urls générées dans les controllers, vous pouvez outrepasser la méthode url_options dans votre controller application. Vous pouvez forcer le protocole des urls générées en fonction des rails env comme suit:

 def url_options
    super
    @_url_options.dup.tap do |options|
      options[:protocol] = Rails.env.production? ? "https://" : "http://"
      options.freeze
    end
  end

cet exemple fonctionne dans les rails 3.2.1, Je ne suis pas exactement sûr pour les versions précédentes ou futures.

3
répondu Shamu 2012-03-06 11:19:46

dans les Rails 4 on peut utiliser le force_ssl_redirect before_action pour appliquer ssl pour un seul contrôleur. Veuillez noter qu'en utilisant cette méthode, vos cookies ne seront pas marqués comme étant sécurisés et HSTS n'est pas utilisé.

2
répondu Samuel 2015-04-14 10:59:22

cette réponse est quelque peu tangente à la question initiale, mais je l'enregistre au cas où d'autres finissent ici dans des circonstances similaires à moi-même.

j'ai eu une situation où je devais avoir des Rails utiliser https proto dans les helpers url, etc. même si l'origine de toutes les requêtes n'est pas cryptée ( http ).

maintenant, habituellement dans cette situation (ce qui est normal lorsque les Rails sont derrière un mandataire inversé ou un équilibreur de charge, etc.), le x-forwarded-proto l'en-tête est défini par le proxy inverse ou autre, donc même si les requêtes sont non cryptées entre le proxy & rails (probablement déconseillé dans la production d'ailleurs) rails pense que tout est dans https .

j'avais besoin de courir derrière un tunnel ngrok tls. Je voulais que ngrok résilie le tls avec les certificats letsencrypt que j'avais spécifiés. Cependant, quand il le fait, ngrok n'offre pas la possibilité de personnaliser les en-têtes, y compris le réglage x-forwarded-proto (bien que ce fonctionnalité est prévue à un certain moment dans l'avenir).

la solution s'est avérée très simple: les Rails ne dépendent pas du protocole de l'origine ou si x-forwarded-proto est placé directement, mais sur le Rack env var rack.url_scheme . Donc j'ai juste besoin d'ajouter ce Rack middleware en développement:

class ForceUrlScheme
  def initialize(app)
    @app = app
  end

  def call(env)
    env['rack.url_scheme'] = 'https'
    @app.call(env)
  end
end
2
répondu Michael Johnston 2017-04-24 19:51:52

URLs relatives, par définition, utiliser le protocole et l'hôte actuels. Si vous souhaitez modifier le protocole utilisé, vous devez fournir l'URL absolue. Je suivrais les conseils de Justice et créerais une méthode qui fait cela pour vous:

def redirect_to_secure(relative_uri)
  redirect_to "https://" + request.host + relative_uri
end
-1
répondu Michael Sepcot 2009-11-02 17:48:44

ouvrir la classe qui a redirect_to et ajouter une méthode redirect_to_secure_of avec une implémentation appropriée. Puis appelez:

redirect_to_secure_of "/some_directory/"

mettez cette méthode dans le répertoire lib ou quelque part utile.

-3
répondu yfeldblum 2009-11-02 16:30:28