问题:什么是“锁定”Rails Web应用程序的好方法,因此用户必须输入凭据才能解锁(但是这样用户仍然登录到应用程序而无法使用该应用程序解锁它?)
我在做什么
我正在构建一个任务管理应用程序,其行为类似于多个用户使用的自助服务终端。用户可以使用他们的电子邮件地址和密码(完整凭证)登录应用程序,但一旦他们进入,他们就可以通过从列表中选择他们的名字并输入四位数的PIN(简单凭证)来“交换”用户。
为什么有两种凭据?
这是一个多租户应用,用户使用“完整凭据”只需进入应用并选择租户。一旦他们进入,他们将经常更换新员工轮班和其他员工离职,因为多个员工将共享一个工作站。
我没有强制用户重复输入他们的“完整”凭据(通过完全注销/登录),而是创建了一个名称/ PIN集凭据,可以用来轻松交换。一旦他们使用完整凭据登录并选择了他们的租户,该应用程序会提供用户姓名的自动完整列表,因此从列表中选择一个人的姓名,输入PIN码并交换用户非常容易。
请注意,此“交换”功能已构建并正常运行。
为什么我需要锁定应用程序?
当用户登录应用程序和租户时,他们可能需要离开应用程序才能执行其他工作。没有锁定屏幕,他们只有两个选择:完全注销,以便下一个用户必须输入“完整”凭据才能使用该应用程序,或者只是让他们的帐户登录以供任何人使用。
我想让他们在应用程序离开时单击按钮以“锁定”应用程序,以便用户可以“登录”应用程序而不允许其他用户访问其他用户的帐户。一旦他们点击“锁定”他们所能做的只是输入名称/ PIN来解锁,或点击“退出”以完全注销。
以下是典型用例的样子:
我理解的选项
似乎有两种方法可以到这里:
所以我一直在搞乱使用会话变量的方法。这是我一直在尝试的:
有关我如何做到这一点的任何建议,以确保其安全吗?
我被挂断的东西:
关于我目前如何设置的一些注意事项:
答案 0 :(得分:1)
这就是我最终建立的目标。
回答我自己的问题:
我是否应该使用某种应用程序控制器过滤器(在此之前或之前)检查应用程序是否被锁定?我在应用程序控制器中使用before_filter来检查UI是否是锁定。如果它被锁定,我会重定向到“锁定”屏幕。然后我将skip_before_filter添加到我的会话控制器中的相关操作中(当用户导航到“锁定”屏幕时,基本上忽略了before_filter,以及Sessions控制器中的相关锁定/解锁操作。
或者这是应该在视图层中处理的东西吗?在视图层中,我大多只需要创建实际的“锁定”屏幕(用户输入凭据以解锁应用程序)并且我确保在UI被锁定时隐藏导航元素(因此用户不会混淆为什么他们点击“编辑个人资料”并且不要离开锁定屏幕)。
我正在使用cookie来记录UI的当前状态(已锁定或未锁定)。以下是一些代码段:
application_controller.rb
before_filter :confirm_unlocked_ui
private
def confirm_unlocked_ui
if signed_in? && locked_ui?
redirect_to locked_path
end
end
sessions_helper.rb
def locked_ui?
session[:locked] == '1'
end
def lock_ui
session[:locked] = '1'
session[:locked_by] = current_user.id
session[:locked_at] = Time.zone.now
end
def unlock_ui
session.delete(:locked)
session.delete(:locked_by)
session.delete(:locked_at)
end
sessions_controller.rb
def lock
session[:return_to] = params[:return_to] if params[:return_to]
lock_ui
redirect_to locked_path
end
def locked
#essentially just a view
end
def unlock
user = User.find_by_id(params[:session][:unlock_user_id])
if user && user.authenticate_with_pin(params[:session][:pin])
cookies[:auth_token] = user.auth_token
unlock_ui
redirect_back_or root_path
else
flash.now[:error] = "Invalid PIN."
render 'locked'
end
end
def destroy
sign_out
unlock_ui
redirect_to root_path
end
我真的不知道这个解决方案有多“好”,我在这里发布的一个原因是看看其他人是否提出了更好的想法,或者看到潜在的问题,我是如何做到这一点的。< / p>
如果您尝试这样做,可能需要考虑一些更微妙的事情: