Rails 3 SSL路由从httpsredirect到http

这个问题涉及到这个问题和答案(rails-3-ssl-deprecation) ,其中build议使用routes.rb和路由如下处理rails 3中的ssl:

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 } 

我的问题是,链接使用相对path(我认为这是正确的术语),一旦我在一个https页面上的所有其他网站的其他链接,然后使用https。

1)什么是最好的方式返回http页面不需要HTTPS? 我必须设置所有的redirect(我希望注意)还是有更好的方法。 redirect是这样的:

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

2)如果redirect到http是必需的,那么我如何处理一个我希望所有方法都是http的情况? 即foos(/ *path)将是所有foos方法。 但是说我想要foos / upload_foos使用ssl。 我知道如何要求

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

但是如果我把httpredirect到foospathhttps_upload_foos会发生什么情况?

如果你想让你所有的链接能够在http和https之间切换,你必须停止使用_path助手并切换到_url助手。

之后,使用协议参数强制和协议约束的范围使得urls自动切换。

的routes.rb

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

现在在你看来:

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

编辑

这不能解决您在https时返回http的url。 要解决这个问题,你需要重写url_for

在任何帮手

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

这将设置协议为'http',除非它被显式设置(在路由中或调用助手时)。

这是很久以前,我相信它可以改善,但回到一些旧的版本的轨道上,我在应用程序控制器中的代码。 不知道这对Rails 3仍然有效,但可能有一些帮助:

 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是一些全局configuration选项,但您可以忽略此选项。

在每个需要https的控制器中,我会添加before_filter :require_ssl并将该控制器名称及其方法添加到SECURE_ACTIONS 。 这可能可以通过将操作名称传递给之前的filter或其他东西来改善。