Приложение OpenID для рельсов за Apache - PullRequest
0 голосов
/ 29 октября 2010

Я пытаюсь интегрировать простую аутентификацию OpenID через учетные записи Google. Я использую omniauth gem и в моей локальной системе разработки (Win7, ruby ​​1.8.7-p302, rails 2.3.8, omniauth 0.1.5) все работает хорошо.

Проблема показывает его лицо при развертывании на хостинге (HostGator). Приложение (mongrel) запускается через порт 12002, и через cPanel HostGator оно настроено для перезаписи с одного из поддоменов:

RewriteCond %{HTTP_HOST} ^subdomain.mycompany.com$ [OR]
RewriteCond %{HTTP_HOST} ^www.subdomain.mycompany.com$
RewriteRule ^(.*)$ "http\:\/\/127\.0\.0\.1\:12002\/$1" [P,L]

Когда браузер переходит / auth / open_id, он перенаправляется в Google для авторизации, но его обратный_адрес - subdomain.mycompany.com:12002, что, конечно, неверно, потому что Apache не слушает 12002. Мне удалось обезьяна исправить OmniAuth :: Стратегии :: OpenID и Rack :: OpenID, поэтому они собирают адрес без порта, НО теперь на финальной стадии после подтверждения доступа пользователя, если попадает в:

Routing Error
No route matches "/403.shtml" with {:method=>:get}

Полагаю, проблема в том, что адрес моего сайта закодирован (какой-то хэш) в другом параметре запроса авторизации, чтобы избежать

Ответы [ 3 ]

1 голос
/ 02 декабря 2010

Проблема порта связана с тем, как запрос RACK вычисляет порт.Вот патч

require 'rack/utils'
module Rack
  class Request
    def port
      if host_with_port =~ /:(\d+)$/
        $1.to_i
      else
        standard_port
      end
    end

    # Returns the standard \port number for this request's protocol.
    def standard_port
      case protocol
        when 'https://' then 443
        else 80
      end
    end

    # Returns 'https://' if this is an SSL request and 'http://' otherwise.
    def protocol
      ssl? ? 'https://' : 'http://'
    end

    # Is this an SSL request?
    def ssl?
      @env['HTTPS'] == 'on' || @env['HTTP_X_FORWARDED_PROTO'] == 'https'
    end
  end
end

Так rails ActionController :: Request вычисляет порт.

Надеюсь, это поможет

0 голосов
/ 14 февраля 2011

В самой последней версии Omniauth (0.2.0.beta4) вы можете указать full_host в качестве параметра конфигурации и установить его для оценки при каждом запросе или просто использовать фиксированное значение.

Пример (рельсы):

ActionController::Dispatcher.middleware.use OmniAuth::Builder do
    store = Rails.env.development? ? OpenID::Store::Filesystem.new("#{Rails.root}/tmp") : nil
    provider :open_id, store, :name => 'google', :identifier => 'https://www.google.com/accounts/o8/id', :scope => 'email'

    if Rails.env.production?
        configure do |config|
            config.full_host = lambda  do |env|
                req = Rack::Request.new(env)
                "#{req.scheme}://#{req.host}"  # req.host strips port number
            end
        end
    end
end
0 голосов
/ 06 ноября 2010

Ну ...

Ошибка 403 состояла в том, что правила безопасности хостинга были настолько строгими, что ответ Google OpenID (достаточно длинный, чтобы быть подозрительным) был отклонен.Решено с помощью поддержки хостинга.

Чтобы решить проблему с номером порта в параметре return_to (адресуемого freiwillen ), я сделал следующий инициализатор (путь обезьяны):

module OmniAuth
  module Strategies
    # OmniAuth strategy for connecting via OpenID. This allows for connection
    # to a wide variety of sites, some of which are listed [on the OpenID website](http://openid.net/get-an-openid/).
    class OpenID
      protected
      def callback_url
        uri = URI.parse(request.url)
        uri.path += '/callback'

        # by KirylP: to overcome hosting subdomain forwarding to rails port        
        uri.port = '' if request.env.has_key? 'HTTP_X_FORWARDED_SERVER'

        uri.to_s
      end
    end
  end
end

module Rack
  class OpenID
    SERVER_PORT_TO_AVOID = 12002

    private
    def realm_url(req)
      url = req.scheme + "://"
      url << req.host

      scheme, port = req.scheme, req.port
      if scheme == "https" && port != 443 ||
          scheme == "http" && port != 80
        url << ":#{port}" if port != SERVER_PORT_TO_AVOID # KirylP
      end

      url
    end
  end
end

module OpenID
  class Consumer
    def complete(query, current_url)
      message = Message.from_post_args(query)

      current_url.sub!(":#{Rack::OpenID::SERVER_PORT_TO_AVOID}", '') # KirylP

      mode = message.get_arg(OPENID_NS, 'mode', 'invalid')
      begin
        meth = method('complete_' + mode)
      rescue NameError
        meth = method(:complete_invalid)
      end
      response = meth.call(message, current_url)
      cleanup_last_requested_endpoint
      if [SUCCESS, CANCEL].member?(response.status)
        cleanup_session
      end
      return response
    end    
  end
end

Надеюсь, кто-нибудь предложит более элегантное решение.

...