Rails 3 routage SSL redirige de https vers http

Cette question concerne cette question et réponse SO (rails-3-ssl-deprecation) où il est suggéré de gérer ssl dans les rails 3 en utilisant routes.rb et les routes comme:

resources :sessions, :constraints => { :protocol => "https" } # Redirect /foos and anything starting with /foos/ to https. match "foos(/*path)", :to => redirect { |_, request| "https://" + request.host_with_port + request.fullpath } 

Mon problème est que les liens utilisent des chemins relatifs (je pense que c’est le terme correct) et une fois que je suis sur une page https, tous les autres liens vers d’autres pages du site utilisent alors https.

1) Quel est le meilleur moyen de revenir à http pour les pages où https n’est pas nécessaire? Dois-je installer des redirections pour tous (j’espère, note-le) ou existe-t-il un meilleur moyen? Les redirections seraient-elles comme ceci:

 match "foos(/*path)", :to => redirect { |_, request| "http://" + request.host_with_port + request.fullpath } 

2) Si des redirections vers http sont requirejses, comment puis-je gérer un cas où je souhaite que toutes les méthodes soient http sauf une? ie foos (/ * path) serait pour toutes les méthodes foos. Mais disons que je voulais que foos / upload_foos utilise ssl. Je sais comment l’exiger

 scope :constraints => { :protocol => "https" } do match 'upload_foos' => 'foos#upload_foos', :via => :post, :as => :upload_foos end 

mais si je mets la redirection http vers le chemin foos, qu’advient-il de https upload_foos?

Si vous voulez que tous vos liens puissent basculer entre http et https, vous devez cesser d’utiliser l’assistant _path et passer aux assistants _url .

Après cela, l’utilisation d’une étendue avec le paramètre de protocole forcé et la contrainte de protocole fait que les URL changent automatiquement.

routes.rb

 scope :protocol => 'https://', :constraints => { :protocol => 'https://' } do resources :sessions end resources :gizmos 

Et maintenant dans vos vues:

 <%= sessions_url # => https://..../sessions %> <%= gizmos_url # => http://..../gizmos %> 

modifier

Cela ne corrige pas les URL qui retournent à http lorsque vous êtes en https. Pour résoudre ce problème, vous devez remplacer url_for .

Dans n’importe quelle aide

 module ApplicationHelper def url_for(options = nil) if Hash === options options[:protocol] ||= 'http' end super(options) end end 

Cela définira le protocole sur ‘http’ sauf s’il était explicitement défini (dans les routes ou lors de l’appel de l’aide).

C’était il y a longtemps et je suis sûr que cela peut être amélioré, mais sur une ancienne version de rails, j’avais ce code dans le contrôleur d’application. Je ne suis pas sûr que cela soit toujours valable pour Rails 3, mais cela peut être utile:

 private SECURE_ACTIONS = { :login => ["login", "login_customer", "remind_password", "add_customer", "add_or_login_customer"], :store => ["checkout", "save_order"], :order => ["show"] } # Called as a before_filter in controllers that have some https:// actions def require_ssl unless ENV['RAILS_ENV'] != 'production' or @request.ssl? redirect_to :protocol => 'https://', :action => action_name # we don't want to continue with the action, so return false from the filter return false end end def default_url_options(options) defaults = {} if USE_EXPLICIT_HOST_IN_ALL_LINKS # This will OVERRIDE only_path => true, not just set the default. options[:only_path] = false # Now set the default protocol appropriately: if actions = SECURE_ACTIONS[ (options[:controller] || controller_name).to_sym ] and actions.include? options[:action] defaults[:protocol] = 'https://' defaults[:host] = SECURE_SERVER if defined? SECURE_SERVER else defaults[:protocol] = 'http://' defaults[:host] = NON_SECURE_SERVER if defined? NON_SECURE_SERVER end end return defaults end 

USE_EXPLICIT_HOST_IN_ALL_LINKS était une option de configuration globale, mais vous pouvez l’ignorer.

Dans chaque contrôleur nécessitant https, j’appendais before_filter :require_ssl et appendais ce nom de contrôleur et ses méthodes à SECURE_ACTIONS . Cela peut probablement être amélioré en passant les noms des actions au filtre avant, ou quelque chose.