ruby Rails7将会话参数传递给Maven策略

iovurdzv  于 2023-04-20  发布在  Ruby
关注(0)|答案(1)|浏览(102)

我正在使用Devise在Rails 7应用程序中对User进行身份验证,并使用Pundit进行授权。我想扩展标准登录流程,以检查用户是否满足2FA要求。2FA很简单,由外部微服务提供-用户在每次登录时输入他在手机上获得的SMS(文本消息)代码。
简而言之,新的登录流程应该是:

  • 通过设备进行用户身份验证
  • 如果session[:_2fa] == 'success'允许授权
  • 如果session[:_2fa] == 'failed',则重定向到provide_code_path

因为用户每次登录时都必须经历2FA过程,我已经将这些信息存储在会话参数中作为session[:_2fa]。现在要进行所有授权和重定向,我希望能够访问该会话以允许或不允许。我知道这个topic,但它它已经有7年的历史了,所以也许今天有一些现代的方法,而不是仅仅为了访问会话而创建假模型?
代码如下:

# application_controller.rb

class ApplicationController < ActionController::Base
  before_action :authenticate_user!, :authorized_user

  rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized

  def authorized_user
    authorize :global, :_2fa_passed?
  end

  private

  def user_not_authorized
    flash[:alert] = t('errors.user_not_authorized')
    redirect_to provide_code_path
  end
end

# global_policy.rb

class GlobalPolicy < ApplicationPolicy
  def _2fa_passed?
    session[:_2fa] == 'success'
  end
end
z3yyvxxp

z3yyvxxp1#

Pundit在自述文件的“附加上下文”部分对此进行了记录。
代替用户示例,你可以传递pundit用户上下文对象,它将保存用户示例和额外的会话上下文,如2FA身份验证状态。

class UserContext
  attr_reader :user, :second_factor_authenticated

  def initialize(user, second_factor_authenticated)
    @user = user
    @second_factor_authenticated = second_factor_authenticated
  end
end

class ApplicationController
  include Pundit::Authorization

  def pundit_user
    second_factor_authenticated = session[:_2fa] == 'success'
    UserContext.new(current_user, second_factor_authenticated)
  end
end

然后在策略类中将user属性重命名为context,并通过context.user引用用户示例,通过context.second_factor_authenticated引用2FA状态。
所以要回答这个问题-七年后,它仍然是完全可以接受的解决方案。
如果你使用Devise,另一种方法是将临时属性second_factor_authenticated添加到用户类中,并实现自己的.serialize_into_session/.serialize_from_session,将其存储为用户“vector”的一部分(默认情况下只有用户id + auth salt)。

相关问题