2011-12-13 87 views
5

我现在有一个设置,其中我强迫SSL或HTTP,我这个的before_filter需要它在我的应用程序控制器:主机使用Rails 3.1

def force_ssl 
    if params[:controller] == "sessions" 
    if !request.ssl? && Rails.env.production? 
     redirect_to :protocol => 'https://', :status => :moved_permanently 
    end 
    else 
    if request.ssl? && Rails.env.production? 
     redirect_to :protocol => 'http://', :status => :moved_permanently 
    end 
    end 
end 

我希望做的是在使用SSL时使用https://secure.example.com,但在不使用SSL时请使用http://example.com。有没有办法根据我是否使用SSL在主机名之间切换?

+0

何苦强迫用户通过SSL时验证,只要进行身份认证,任何人都可以破解他们与例如会议firesheep,免费会话黑客firefox插件。如果您尝试以这种方式使用SSL,则无法保护用户。相反,如果您的站点的某些部分需要通过SSL进行交付,那么从实际的安全角度来看,您的站点的每个部分都可能需要通过SSL进行交付(或至少在身份验证后的每个部分)。 – yfeldblum

回答

4

首先我将介绍如何在当前版本和早期版本的Rails中强制使用SSL,然后在最后发布了如何在并行中使用HTTP和HTTPS,这正是我想要的。

滑轨> = 3.1

只需在您的环境配置使用config.force_ssl = true

# config/application.rb 
module MyApp 
    class Application < Rails::Application 
    config.force_ssl = true 
    end 
end 

您还可以选择性地启用https,具体取决于当前的Rails环境。例如,您可能希望在开发时关闭HTTPS,并在分段/生产中启用它。

# config/application.rb 
module MyApp 
    class Application < Rails::Application 
    config.force_ssl = false 
    end 
end 

# config/environments/production.rb 
MyApp::Application.configure do 
    config.force_ssl = true 
end 

Rails的< 3.1

万一你有没有Rails的3.1和想的一样功能的任何项目。通过将以下行添加到您的环境配置中来启用HTTPS。

config.middleware.insert_before ActionDispatch::Static, "Rack::SSL"

注意,我传递Rack::SSL作为字符串委托类的装载在Rails应用程序初始化结束。另请注意,中间件必须插入堆栈中的特定位置,至少在ActionDispatch::StaticActionDispatch::Cookies之前。

不要忘记在您的Gemfile中定义Rack :: SSL依赖关系。

# Gemfile 
gem 'rack-ssl', :require => 'rack/ssl' 

启用HTTPS和HTTP并行

Rack::SSL有一个非常有趣的和未公开的特性。您可以通过:exclude选项来确定何时启用/禁用HTTPS的使用。

以下代码仅在请求来自HTTPS连接时启用Rack::SSL及其所有筛选器。

config.middleware.insert_before ActionDispatch::Static, Rack::SSL, :exclude => proc { |env| env['HTTPS'] != 'on' } 

以下两个网址将继续工作,但第一个将触发Rack::SSL过滤器。

https://secure.example.com
http://example.com

+0

我在使用force_ssl之前(我在Rails 3.1中),但是我没有找到一种方法来强制http,因为我不想使用SSL,所以我只是在自己的应用程序控制器中推出了自己的解决方案。有没有办法自定义force_ssl? –

+0

你可以在ForceSSL模块中写一个自定义的类方法,它可以做到与ForceSSL相反的功能,如果你愿意,我可以发布一个例子吗? – digicazter