我正在使用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
1条答案
按热度按时间z3yyvxxp1#
Pundit在自述文件的“附加上下文”部分对此进行了记录。
代替用户示例,你可以传递pundit用户上下文对象,它将保存用户示例和额外的会话上下文,如2FA身份验证状态。
然后在策略类中将
user
属性重命名为context
,并通过context.user
引用用户示例,通过context.second_factor_authenticated
引用2FA状态。所以要回答这个问题-七年后,它仍然是完全可以接受的解决方案。
如果你使用Devise,另一种方法是将临时属性
second_factor_authenticated
添加到用户类中,并实现自己的.serialize_into_session
/.serialize_from_session
,将其存储为用户“vector”的一部分(默认情况下只有用户id + auth salt)。