我将Rails Stack与
一起使用现在,我对电子邮件确认和未验证用户的访问权限有一定要求。假设页面分为3类:
case 1
-不需要身份验证。case 2
-需要认证,还需要确认用户。case 3
-需要进行身份验证(正确的用户名和密码组合),但无需确认用户即可访问它们。通过设计和确认,实现case 1
和case 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
这几乎不能用于登录,但不能用于注册。同样,这是实现它的极其糟糕的方法。我应该如何解决这个问题?其他功能正常工作。
答案 0 :(得分:5)
除了覆盖confirmed?
之外,您还可以覆盖confirmation_required?
模型方法(docs):
# user.rb
class User < ActiveRecord::Base
protected
def confirmation_required?
false
end
end
此后,您可以自己处理确认逻辑,方法是在控制器需要确认时通过在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
答案 1 :(得分:2)
您应该看一下宝石'pundit'-它与devise配合得很好。
https://github.com/varvet/pundit
您编写的策略将涵盖每个授权要求,而不是编写控制器的before_actions等,然后在控制器内部使用这些策略。
例如,在控制器中:
SELECT '[' + s.name + '].[' + o.name + '].[' + i.name + ']' AS keyname
from sys.foreign_keys i
INNER JOIN sys.objects o ON i.parent_object_id = o.object_id
INNER JOIN sys.schemas s ON o.schema_id = s.schema_id
WHERE i.is_not_trusted = 1 AND i.is_not_for_replication = 0;
然后,您的政策将保存在app / policies / example_policy.rb
下class ExampleController < ApplicationController
before_action { authorize :example }
def case_one
# action
end
def case_two
# action
end
def case_three
# action
end
end
它真的很好用,特别是在您要确定针对某种资源的授权的其他情况下。