Rails 3 SSL弃用警告

28
我正在将一个应用程序升级到Rails 3.0.0,想知道添加SSL的标准方法是否已更改(我模糊地记得演示表明路由器现在可以处理SSL,但我不确定它是否仅用于演示目的)。我目前使用"ssl_requirement" gem,但它会出现以下警告:
 

DEPRECATION WARNING: Using #request_uri is deprecated. Use fullpath instead. (called from ensure_proper_protocol at /Library/Ruby/Gems/1.8/gems/ssl_requirement-0.1.0/lib/ssl_requirement.rb:53)

此外,当处理新的'data-method'属性时,它似乎会出错。例如:

<%= link_to "Logout", user_path, :method => :delete %>

在应用程序的SSL部分访问时工作正常,但是当从非SSL部分(用户控制器中的所有操作都需要SSL,尽管我知道销毁操作不会传输安全数据)跟随时会失败(尝试呈现显示操作)。

4个回答

46

在Rails 3中确实非常简单。在config/routes.rb文件中:

MyApplication::Application.routes.draw do
  resources :sessions, :constraints => { :protocol => "https" }
end

或者,如果您需要强制多个路由使用 SSL:

MyApplication::Application.routes.draw do
  scope :constraints => { :protocol => "https" } do 
    # All your SSL routes.
  end
end

连接到 SSL 路由可以这样做:

<%= link_to "Logout", sessions_url(:protocol => 'https'), :method => :delete %>
如果您希望将某些控制器(或实际上是某些子路径)自动重定向到等效的基于https的URL,您可以将以下内容添加到路由中(我希望这部分更简单):
# Redirect /foos and anything starting with /foos/ to https.
match "foos(/*path)", :to => redirect { |_, request|
  "https://" + request.host_with_port + request.fullpath }

1
这似乎比使用“ssl_requirement”更复杂。它是Rails 3中的新标准方法,还是“ssl_requirement”仍然可用?谢谢。 - Kevin Sylvestre
1
@Kevin:除了自动重定向之外,我认为这很容易。此外,所有这些都可以使用标准路由DSL完成,在Rails 2中无法完成,因此需要使用外部库。 - molf
4
在开发环境中,使用scope :constraints => { :protocol => Rails.env.production? ? 'https' : 'http' } do ... end来限定协议。 - Ryenski
5
请注意,在Rails 3.1中,它变得更简单了:http://www.simonecarletti.com/blog/2011/05/configuring-rails-3-https-ssl/ - molf
您提供的 match 规则创建了一个重定向循环。 - Raphael
@KevinSylvestre 这有什么更复杂的?你可以使用 scope 将所有 https 路由包装在一个地方,而不是在每个单独的控制器中进行此操作并尝试跟踪它。这样更加DRY。 - bigpotato

20

在花了一个下午的时间寻找最佳解决方案后,我选择了这篇文章中描述的方法:http://clearcove.ca/blog/2010/11/how-to-secure-a-rails-app-on-heroku-with-ssl-firesheep/,该文章引用了这篇文章:Force SSL using ssl_requirement in Rails 2 app

基本上按照以下步骤操作即可:

# lib/middleware/force_ssl.rb
class ForceSSL
  def initialize(app)
    @app = app
  end

  def call(env)
    if env['HTTPS'] == 'on' || env['HTTP_X_FORWARDED_PROTO'] == 'https'
      @app.call(env)
    else
      req = Rack::Request.new(env)
      [301, { "Location" => req.url.gsub(/^http:/, "https:") }, []]
    end
  end
end

# config/application.rb
config.autoload_paths += %W( #{ config.root }/lib/middleware )

# config/environments/production.rb
config.middleware.use "ForceSSL"

1
我更喜欢这种方法,因为@molf的解决方案即使在开发环境中也需要SSL。 - Matt Darby

14

虽然话题比较老,但是对于需要搜索的人还是很有用:

在 *app/controller/your_controller.rb* 文件中:

 class LostPasswordsController < ApplicationController

   force_ssl

   def index
     #....
   end
 end 

如果全局使用它,则在应用程序控制器中使用

http://apidock.com/rails/ActionController/ForceSSL/ClassMethods/force_ssl

谢谢S.L.提供的提示


感谢您。结合“except”和“only”选项,这是选择性SSL的绝佳解决方案。 - LouieGeetoo
顺便提一下,config.force_ssl 和控制器 force_ssl 之间是有区别的。详情请见:http://www.eq8.eu/blogs/14-config-force_ssl-is-different-than-controller-force_ssl - equivalent8

1
在较新的Rails版本(至少3.12+),你可以针对不同的环境使用以下设置:
在config/environments/production.rb中(或其他环境文件):
# Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
config.force_ssl = true

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接