[英]Kiosk-like web application - how do I “lock” the app?
Question: What's a good way to "lock" a Rails web application so a user must enter credentials to unlock it (but such that the user is still logged into the app and simply can't use the app without unlocking it)? 问题:“锁定” Rails Web应用程序的一种好方法是什么,以便用户必须输入凭据才能对其进行解锁(但这样用户仍然登录到该应用程序中,并且无法在未解锁的情况下使用该应用程序)?
What I'm doing 我在做什么
I'm building a task management app that behaves like a kiosk to be used by multiple users. 我正在构建一个行为管理应用程序,其行为类似于供多个用户使用的信息亭。 Users can log in to the app using their email address and password (full credentials), but once they're in, they can "swap" users by selecting their name from a list and entering a four-digit PIN (easy credentials). 用户可以使用其电子邮件地址和密码(完整凭据)登录到该应用程序,但是一旦进入,便可以通过从列表中选择其名称并输入四位数的PIN(简单凭据)来“交换”用户。
Why have two types of credentials? 为什么有两种凭证?
This is a multi-tenant app, and users use "full credentials" to simply get into the app and choose a tenant. 这是一个多租户应用程序,用户使用“完整凭据”即可进入该应用程序并选择一个租户。 Once they're in, they will frequently swap out as new employees come on shift and other employees leave because multiple employees will share a single work station. 一旦进入,随着新员工的轮班和其他员工的离职,他们将频繁调换工作,因为多个员工将共享一个工作站。
Rather than forcing users to repeatedly enter their "full" credentials (by doing a full logout/login), I've created a name/PIN set of credentials they can use to easily swap. 我没有强迫用户反复输入其“完整”凭据(通过执行完整的注销/登录),而是创建了一个名称/ PIN凭据集,可用于轻松交换。 Once they're logged in with full credentials and have chosen their tenant, the app provides an autocomplete list of user's names, so it's very easy to select one's name from the list, enter the PIN and swap users. 一旦他们以完整的凭据登录并选择了他们的租户,该应用程序就会提供用户名的自动完成列表,因此从列表中选择一个人的名字,输入PIN并交换用户非常容易。
Note that this "swapping" functionality is already built and working. 请注意,此“交换”功能已经构建并且可以正常工作。
Why do I need to lock the app? 为什么需要锁定应用程序?
When a user is logged in to the app and a tenant, they may need to leave the app to go do other work. 当用户登录到应用程序和租户时,他们可能需要离开应用程序才能执行其他工作。 Without a lock screen, they only have two choices: fully log out so that the next user has to enter "full" credentials to use the app or just leave their account logged in for anyone to mess with. 没有锁定屏幕,他们只有两种选择:完全注销,以便下一个用户必须输入“完整”凭据才能使用该应用程序,或者仅使他们的帐户登录才能被任何人使用。
I would like to allow them to click a button to "lock" the app when they walk away so that users can leave the app "logged in" without allowing other users to access others' accounts. 我想允许他们在离开时单击按钮以“锁定”该应用程序,以便用户可以使该应用程序“登录”,而不允许其他用户访问其他用户的帐户。 Once they click "lock" all they can do is enter a name/PIN to unlock it, or click "sign out" to fully log out. 一旦他们单击“锁定”,他们所能做的就是输入名称/ PIN码以对其进行解锁,或者单击“退出”以完全注销。
Here's what a typical use-case would look like: 这是典型的用例:
The options as I understand them 据我了解的选择
It seems like there are two ways to go here: 看来这里有两种方法:
JavaScript makes me nervous because it's pretty hackable. JavaScript让我感到紧张,因为它很容易被入侵。 I want to make sure the app is actually secure. 我想确保该应用程序实际上是安全的。
So I've been messing with ways of using session variables to do this. 因此,我一直在弄乱使用会话变量执行此操作的方法。 Here is what I've been trying: 这是我一直在尝试的方法:
Any suggestions on how I might do this so that it's secure? 关于如何执行此操作以确保安全的任何建议?
Things I'm hung up on: 我挂断的事情:
Some notes on how I'm currently set up: 关于我目前的设置方式的一些注意事项:
Here's what I ended up building. 这就是我最终建立的。
To answer my own questions: 要回答我自己的问题:
Should I be using some sort of application controller filter (before or around) to check to see if the app is locked? 我是否应该使用某种应用程序控制器过滤器(之前或前后)来检查应用程序是否被锁定? I am using a before_filter in my Application Controller to check whether the UI is locked. 我在应用程序控制器中使用before_filter检查UI是否已锁定。 If it's locked, I redirect to the "locked" screen. 如果已锁定,我将重定向到“锁定”屏幕。 I then added a skip_before_filter to the relevant actions in my Sessions Controller (essentially ignoring that before_filter when the user is navigating to the "locked" screen and related lock/unlock actions in the Sessions controller. 然后,我在我的Sessions控制器中的相关动作中添加了skip_before_filter(当用户导航到Sessions控制器中的“锁定”屏幕和相关的锁定/解锁动作时,基本上忽略了before_filter。
Or is this something that should be handled in the view layer? 还是这应该在视图层中处理? In the view layer, I mostly just needed to create the actual "locked" screen (where a user enters credentials to unlock the app), and I make sure to hide navigation elements while the UI is locked (so the user isn't confused as to why they click "Edit Profile" and don't leave the lock screen). 在视图层中,我几乎只需要创建实际的“锁定”屏幕(用户输入凭据即可解锁应用程序),并且确保在UI锁定时隐藏导航元素(因此用户不会感到困惑) (为什么他们单击“编辑个人资料”而不离开锁定屏幕)。
I'm using cookies to record the current state of the UI (locked or not). 我正在使用cookie记录UI的当前状态(是否锁定)。 Here are some code snippets: 以下是一些代码段:
application_controller.rb 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 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 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
I really don't know how "good" this solution is, and one reason I'm posting it here is to see if others come up with better ideas or see any issues lurking with how I've done this. 我真的不知道这个解决方案有多“好”,我在这里发布它的一个原因是,看看其他人是否提出了更好的主意,或者发现我如何做到这一点潜伏着任何问题。
Some more subtle things you might want to think about if you're trying this: 如果要尝试此操作,可能需要考虑一些更细微的事情:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.