14

Previously, I had been using ssl_requirement to give us fine grained control over which pages were served over ssl and which were served over plain http.

According to the ssl_requirement's own wiki, it has been superseded by rails 3.1's Force SSL. However this does not seem to be the case. Force SSL doesn't seem to expose an option to go in the opposite direction, there is no way to force a page to sent via regular http.

What is the correct Rails 3.1 way to force a page to be displayed in plain http? Does Force SSL truly supersede ssl_requirement?

ghempton
  • 7,777
  • 7
  • 48
  • 53

6 Answers6

26

What Justice said. Some people feel strongly about browsing with SSL for everything. It's now trivial to snoop non-SSL sessions, so you should go out of your way to accomodate people who want to use it.

However.

It should be fairly easy to accomplish using a before_filter:

class ApplicationController < ActionController::Base
  before_filter do
    if request.ssl? && Rails.env.production?
      redirect_to :protocol => 'http://', :status => :moved_permanently
    end
  end
end
Pete Hodgson
  • 15,644
  • 5
  • 38
  • 46
Joost Baaij
  • 7,538
  • 3
  • 32
  • 34
  • Yeah, thats exactly what ssl_requirement did. – ghempton Sep 26 '11 at 19:56
  • Actually, it's the exact opposite. Isn't that what you asked? – Joost Baaij Sep 27 '11 at 11:42
  • No, I was asking if force-ssl (what replaced ssl_requirement) also allowed for this. – ghempton Sep 27 '11 at 20:49
  • Since we are both being pedantic. Your question was, literally: "What is the correct Rails 3.1 way to force a page to be displayed in plain http?". To which I gave a correct answer. Your second question "Does Force SSL truly supersede ssl_requirement?" was not answered by anyone. – Joost Baaij Sep 27 '11 at 20:55
  • Gave you +1 for pedantic rigor :). However, your answer was indeed partially correct, in that it gave the correct Rails 3.1 way to do this. Similarly my response was in the affirmative. To your second question, it could be understood that I am replying no to ssl_requirement doing the exact opposite (which it doesn't, it does both). – ghempton Sep 28 '11 at 00:56
  • 5
    This should be `request.ssl?` instead of `request.ssl`, which doesn't exist. – Eric Yang Dec 12 '11 at 23:32
4

The code for Force SSL is pretty easy to read.

https://github.com/rails/rails/blob/master/actionpack/lib/action_controller/metal/force_ssl.rb

It doesn't seem to do the reverse and force http to be used. It provides the only and except options to control which actions and controllers SSL is to be required for, but doesn't provide a way to force HTTP to be used instead of https.

Rob Dawson
  • 1,349
  • 10
  • 21
  • Was hoping there was a baked rails 3.1 way to do this. Marked as correct because this confirms my suspicions that there isn't. – ghempton Sep 26 '11 at 19:57
  • Now it seems that you can use an if or unless clause in the controller. See the same file you posted. – e3matheus Apr 30 '12 at 15:59
2

To use force_non_ssl the exact same way as force_ssl check this Rails Concern: https://gist.github.com/joost/6989118

Accepts options like:

force_non_ssl only: :show
force_non_ssl except: :show, notice: "Hi this is now insecure :)"
joost
  • 6,549
  • 2
  • 31
  • 36
1

I simplified joost's code to all I needed. Thanks joost

if request.ssl?
  options = {
    :protocol => 'http://',
    :host     => request.host,
    :path     => request.fullpath,
    :status   => :moved_permanently
  }
  non_secure_url = ActionDispatch::Http::URL.url_for(options.slice(*URL_OPTIONS))
  redirect_to non_secure_url, options.slice(*REDIRECT_OPTIONS)
end
Alex Levine
  • 1,489
  • 15
  • 16
0

For those who just need to disable force_ssl behaviour on their whole app for a short time on local machine like me, you can simply do this in your ApplicationController:

def self.force_ssl *a
  warn "force_ssl disabled globally"
end

Just make sure not to commit it to your codebase.

hakunin
  • 4,041
  • 6
  • 40
  • 57
-7

Why would you ever want to force HTTP over HTTPS?

A lot of us out here browse with SSL everywhere. Please don't put the rest of us at risk simply because you don't like helping us out with our own security.

For most of us, security is important, even if most of us don't understand its importance or know how to obtain it. For some of us, security is life and death critical.

Some pages must be served over SSL. Although, in my view, if any part of your site requires being served over SSL, then the entire site requires it (a MITM can change the link to the SSL page as it is rendered on the non-SSL page to point to a non-SSL proxy that the MITM controls). No page ever requires being served without SSL.

yfeldblum
  • 65,165
  • 12
  • 129
  • 169
  • 5
    The classic you should be doing it this way instead response. There are many reasons for forcing http. Some 3rd party APIs and widgets (e.g. tweet button) are only exposed in http. Sometimes you want better performance for a non-sensitive site. – ghempton Sep 26 '11 at 19:01
  • 6
    Not to mention that when you're creating your own API you might actually not want some requests to have the overhead of an SSL connection… There's no reason to use HTTPS unless you need to, not the other way around. – levifig Nov 11 '11 at 15:09
  • There's situation where ssl just makes things worse, like youtube embedded videos that complain about ssl. – Pod May 21 '13 at 20:34
  • Another great reason is when you're terminating SSL at your load balancer, and your load balancer connects to your Rails app with regular HTTP. – ndbroadbent Aug 05 '16 at 18:20