Authlogic根URL基于经过身份验证的状态

时间:2011-11-25 21:24:51

标签: ruby-on-rails ruby ruby-on-rails-3 authlogic

我希望能够根据Authlogic的登录/退出状态在routes.rb中设置根URL。以下是我需要做的一个例子:

root :to => 'users#index', :constraints => lambda { |request| # ??? }  
root :to => 'welcome#index'  
get '/' => 'users#index', :as => 'user_root'

这将使登录用户能够转到users#index并注销用户,无需进行重定向即可转到welcome#index 。我知道如何设置一个before_filter并相应地重定向,但我宁愿不这样做。

我知道Devise可以实现这一点,但我需要为Authlogic解决这个问题。类似的问题here没有答案。

3 个答案:

答案 0 :(得分:1)

您可以非常轻松地创建自定义路径约束。响应matches?的任何对象都可以传递给:constraints路由选项。要检查Authlogic身份验证,您需要从ApplicationController中提取Authlogic方法并将它们放在其他位置。无论如何,我建议使用这些问题。

# app/concerns/authlogic_methods.rb
module AuthlogicHelpers
  extend ActiveSupport::Concern

  module InstanceMethods
    private # All methods are private

    def current_user_session
      return @current_user_session if defined?(@current_user_session)
      @current_user_session = UserSession.find
    end

    def current_user
      return @current_user if defined?(@current_user)
      @current_user = current_user_session && current_user_session.user
    end
  end
end

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  include AuthlogicHelpers
end

# config/initializers/route_constraints.rb
module RouteConstraints
  class LoggedIn
    include AuthlogicHelpers
    def matches?(request)
      current_user
    end
  end
end

# config/routes.rb
constraints RouteConstraints::LoggedIn.new do
  root :to => 'dashboard#show'
end

请注意,我们正在实例化一个新的RouteConstraints::LoggedIn对象。这是因为Authlogic方法current_usercurrent_user_session被定义为实例方法并创建实例变量 - 如果它们没有为每个请求分开,您将不确定用户是否实际登录或另一个人之前登录过。

如果Authlogic尝试直接访问params可能会遇到问题。在这种情况下,您可能需要覆盖UserSession.new方法以接受request对象作为参数,并调用request.params来获取参数。

答案 1 :(得分:1)

Authlogic已经拥有本地机器(已针对Rails 6.0和Authlogic 6.0进行了测试):

class AuthlogicSignedInConstraint
  def matches?(request)
    Authlogic::Session::Base.controller = Authlogic::ControllerAdapters::AbstractAdapter.new(request)
    user_session = UserSession.find
    user_session && user_session.user
  end
end

答案 2 :(得分:0)

最新版本的Authlogic需要实例化控制器对象,否则无法找到加载会话所需的会话数据。

实际上,authlogic/controller_adapters/下包含的是用于各种控制器实现的适配器:Rails控制器,Sinatra和Rack。

该接口非常简单,因此我编写了一个适配器来与约束中可以访问的ActionDispatch::Request一起使用。

这已在Rails 4.2上进行了测试,Rails 5应该相似。

class AuthlogicRequestAdapter
  attr_reader :request

  def initialize(request)
    @request = request
  end

  def authenticate_with_http_basic
  end

  def cookies
    request.cookies
  end

  def params
    request.params
  end

  def session
    _, session_hash = Rails.application.config.session_store.new(Rails.application, Rails.application.config.session_options).load_session(request.env)
    session_hash
  end
end

在Rails中使用的示例

路线约束

class UserRouteConstraint
  def matches?(request)
    Authlogic::Session::Base.controller = AuthlogicRequestAdapter.new(request)
    user = UserSession.find

    if user&.record.present?
      true
    else
      false
    end
  end
end

routes.rb

MyRailsApp::Application.routes.draw do
  # ... other routes

  constraints(UserRouteContraint.new) do
    root :to => 'users#index'
  end

  root :to => 'welcome#index'  
  get '/' => 'users#index', :as => 'user_root'
end