Rails 3 SSL-маршрутизация перенаправляет с https на http - PullRequest
42 голосов
/ 22 октября 2010

Этот вопрос относится к этому SO вопросу и ответу (rails-3-ssl-deprecation) , где предлагается обрабатывать ssl в rails 3, используя rout.rb и маршруты типа:

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 }

Моя проблема в том, что ссылки используют относительные пути (я думаю, что это правильный термин), и как только я попадаю на страницу https, все остальные ссылки на другие страницы сайта используют https.

1) Какой лучший способ вернуться на http для страниц, где https не требуется?Нужно ли настраивать перенаправления для всех (надеюсь, заметьте) или есть лучший способ.Будут ли перенаправления выглядеть так:

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

2) Если требуются перенаправления обратно на http, как мне обработать случай, когда я хочу, чтобы все методы были http, кроме одного?то есть foos (/ * путь) будет для всех методов foos.Но, скажем, я хотел, чтобы foos / upload_foos использовал ssl.Я знаю, как это сделать

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

, но если я добавлю http-перенаправление на путь foos, что произойдет с https upload_foos?

Ответы [ 2 ]

43 голосов
/ 22 октября 2010

Если вы хотите, чтобы все ваши ссылки могли переключаться между http и https, вам следует прекратить использование помощника _path и переключиться на помощники _url.

После этого при использовании области с принудительным параметром протокола и ограничением протокола URL-адреса автоматически переключаются.

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

resources :gizmos

А теперь в ваших взглядах:

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

Редактировать

Это не исправляет URL, которые возвращаются к http, когда вы находитесь в https. Чтобы это исправить нужно переопределить url_for.

В любом помощнике
module ApplicationHelper
  def url_for(options = nil)
    if Hash === options
      options[:protocol] ||= 'http'
    end
    super(options)
  end
end

Это установит протокол на «http», если он не был установлен явно (в маршрутах или при вызове помощника).

0 голосов
/ 22 октября 2010

Это было давно, и я уверен, что это можно улучшить, но вернувшись к какой-то старой версии rails, я имел этот код в контроллере приложения. Не уверен, что это все еще верно для 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 был некоторой опцией глобальной конфигурации, но вы можете проигнорировать это.

В каждом контроллере, который требовал https, я бы добавил before_filter :require_ssl и добавил бы имя этого контроллера и его методы к SECURE_ACTIONS. Это, вероятно, можно улучшить, передав имена действий в фильтр before или что-то в этом роде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...