0

I checked out the gem called ssl_requirement which enforces SSL on certain actions and enhances the url and path helpers, it seems promising overall but it's too outdated and not quite well maintained.

Does anyone know any updated alternatives that provide such convenience:

  1. Require SSL in controllers not in routes file.
  2. Automatically choose https:// on URL and Path helpers without having to ruin the code with: :protocol => 'https'?
  3. Ability to disable the whole SSL enforcement in development
CodeOverload
  • 47,274
  • 54
  • 131
  • 219
  • `gem 'bartt-ssl_requirement', '~>1.4.0', :require => 'ssl_requirement'`. See the repo here: https://github.com/bartt/ssl_requirement – geoff Aug 27 '14 at 18:10

1 Answers1

3

You don't need a gem - you can just write a little helper to do this.

in ApplicationController:

def force_ssl(options = {})
  host = options.delete(:host)
  unless request.ssl? or Rails.env.development?
    redirect_options = {:protocol => 'https://', :status => :moved_permanently}
    redirect_options.merge!(:host => host) if host
    flash.keep
    redirect_to redirect_options and return
  else
    true
  end
end

And then in your controllers:

before_filter :force_ssl, :only => [:login]

This does not satisfy your second requirement of automatically choosing the https protocol on path helpers, but that's not achievable with a controller-specified SSL enforcement, since the route helpers don't care about what's happening on a controller level. That is actually mutually exclusive with controller-enforced SSL, because if your routes specify HTTPS, then they won't resolve a non-HTTPS URL to a controller action, which means that your force_ssl filter would never be hit. You could achieve this by duplicating your routing, however, so that you have both HTTPS-scoped and unscoped routes, with the unscoped routes being defined before the HTTPS-scoped routes, so that the HTTPS-scoped versions assume the helper names. This does mean duplication, though.

You might be able to achieve that with a little helper method, though. I haven't tested this, but the concept should work:

def route_with_https_preference(&block)
  &block.call
  scope :protocol => 'https://', :constraints => { :protocol => 'https://' } do
    instance_eval &block
  end
end

route_with_https_preference do
  resources :gizmos do
    resources :widgets
  end
end

You can achieve SSL-scoped routing in your routes file easily enough (see this answer for details), but it does mean that you have to use the _url helpers rather than the _path helpers, as a protocol switch requires a full-qualified URL.

Community
  • 1
  • 1
Chris Heald
  • 61,439
  • 10
  • 123
  • 137