允许未经证实的用户访问需要身份验证的某些页面

kaw*_*a21 7 ruby-on-rails devise warden ruby-on-rails-3 devise-confirmable

我使用Rails堆栈

  • 设计
  • 看守
  • 可证实

现在我对未经验证的用户的电子邮件确认和访问提供有一定的要求.假设有3类页面:

  1. case 1 - 无需身份验证.
  2. case 2 - 需要身份验证,还需要确认用户.
  3. case 3 - 需要身份验证(正确的用户名和密码组合),但无需确认用户访问它们.

有了设计和确认,实施case 1case 2轻而易举.用户登录/注册后,我会重定向到"确认您的电子邮件页面".

我的问题是case 3.假设用户进行了他的登录/注册.他尚未确认他的电子邮件地址,但应该允许访问某些case 3路线.当他访问案例3路线时,我希望:

  • 没有重定向
  • 有效会话

设置确认可以允许确认的用户访问所有页面,也可以不允许.它不允许访问具有身份验证但未经确认的某些页面.

我尝试confirmed?通过实现这个逻辑来覆盖设计:

class ApplicationController < ActionController::Base
   before_filter :verify_user
   def verify_user
       $flag = true if CERTAIN_ROUTES.include?(action_class)
   end
end

class User < ActiveRecord::Base
   def confirmed?
      $flag || !!confirmed_at
   end
end
Run Code Online (Sandbox Code Playgroud)

这几乎不适用于登录,但不适用于注册.而且,这是实现它的极其糟糕的方法.我该如何处理这个问题?其他功能很好.

sma*_*ton 5

除了覆盖外,confirmed?您还可以覆盖confirmation_required?模型方法(docs)

# user.rb
class User < ActiveRecord::Base
  protected

  def confirmation_required?
    false
  end
end
Run Code Online (Sandbox Code Playgroud)

之后,您可以通过before_action在控制器需要确认时重定向所有未确认的用户来自己处理确认逻辑,也可以将其纳入授权逻辑中(例如,使用专家)。

class ApplicationController < ActionController::Base
   def needs_confirmation
     redirect_to root_path unless current_user.confirmed?
   end
end

class SomeController < ApplicationController
  before_action :needs_confirmation
end
Run Code Online (Sandbox Code Playgroud)

  • 然后只需将“before_action”放在“ApplicationController”中,并在您想要未经确认的访问的控制器中使用“skip_before_action:needs_confirmation”。https://apidock.com/rails/v4.2.7/AbstractController/Callbacks/ClassMethods/skip_before_action (2认同)