我第一次尝试GWT RequestFactory(RF(,并尝试实现一个简单的登录屏幕和身份验证系统(没有使用任何花哨的东西,只是在这里摆弄基础知识(。我希望实现的基本用户体验与课程相当:
用户将看到一个登录屏幕(电子邮件和密码以及"登录"按钮(。当他们单击该按钮时,我想使用 RF 将他们的凭据发送到服务器(使用 ValueProxy
,因为这些不是实体(并对其进行身份验证。如果凭据正确,他们现在已"登录"到系统,GWT应用程序将下载一个全新的模块,他们将被重定向到其帐户的主菜单。如果凭据不正确,我想发回一个字符串,说明电子邮件或密码不正确,并且它们仍然"注销"了应用程序。
关于我昨天发布的这个问题,我现在已经弄清楚了如何使用 RF 公开一个SignInOutService
,该具有用于尝试登录用户的signIn(SignIn)
方法,以及用于将用户注销系统的signOut(SignOut)
方法。但是现在我实际上正在尝试实现该服务,这是我到目前为止所拥有的:
public class DefaultSignInOutService {
// Try to sign the user into the system.
public String signIn(SignIn signIn) {
// The SignIn object contains the email/hashed password the user tried
// signing-in with, as well as other metadata I'm looking to store for
// security purposes (IP address, user agent, etc.).
String email = signIn.getEmail();
String hashedPassword = signIn.getHashedPassword();
// This will be set to a non-null value if the sign-in attempt fails.
// Otherwise (on successful sign-in) it will stay NULL. The client-side
// handler will know what to do with the UI based on this value.
String failReason = null;
// For this simple example, the password is "12345" and below is it's MD5 hash.
// Hey! That's the combination on my luggage!
if(!"skroob@spaceballs.example.com".equals(email) || !"827ccb0eea8a706c4c34a16891f84e7b".equals(hashedPassword))
failReason = "Login failed; incorrect email or password.";
else {
// Log the user into the system...
// TODO: How?
}
return failReason;
}
// Sign the user out of the system.
public void signOut(SignOut signOut) {
// The SignOut object should reference the user attempting to sign out, as well as a reason
// for why the sign out is occurring: the user manually requested to be signed out, or they
// "expired" due to inactivity or navigating the browser away from the app, and so the system
// auto-signed them out, etc.
// TODO: How?
return;
}
}
所以现在,我已经实现了我的超级简单的电子邮件/密码检查,我已经准备好编写代码,以某种方式将用户登录到应用程序(这样他们就不会一遍又一遍地看到登录屏幕(。我窒息着下一步该做什么。
我正在尝试找到解决方案的问题:
- GWT RF 是否以某种方式基于会话或令牌?如果是这样,在注释行"
Log the user into the system...
"下,我可以写什么代码说">此用户现在已通过身份验证,设置一些 cookie 或会话变量以使其如此!我问这个问题是因为一旦他们登录并被路由到新模块和主菜单,GWT 将需要一种方法来验证此后的每个后续 RF 请求。 signOut()
方法需要重置/清除/取消什么才能清除这些 cookie/会话变量?换句话说,我如何实际注销用户,因此,如果他们尝试转到其主菜单的 URL(同样只有在他们登录后才能访问(,他们将被重定向到登录屏幕?- 如何实现 15 分钟的非活动超时,即用户在一定时间长度后自动注销应用?我认为一旦我看到上面的问题 #1 和 #2 是如何工作的,这个答案就会变得更加明显。
有人告诉我,我可能需要两个 servlet 和/或过滤器:一个用于处理未经身份验证的 RF 请求(当用户注销或尚未登录时(,另一个用于处理经过身份验证的 RF 请求(一旦用户主动登录(。但我看不出它们如何融入这里的整体情况。
最简单的方法是在会话中存储身份验证详细信息。
public String signIn(SignIn signIn) {
...
if(!"skroob@spaceballs.example.com".equals(email) || !"827ccb0eea8a706c4c34a16891f84e7b".equals(hashedPassword))
failReason = "Login failed; incorrect email or password.";
else {
RequestFactoryServlet.getThreadLocalRequest().getSession().setAttribute("auth", signIn);
}
return failReason;
}
public void signOut(SignOut signOut) {
RequestFactoryServlet.getThreadLocalRequest().getSession().removeAttribute("auth");
return;
}
在每个请求中,您可以检查SignIn
对象是否仍然存在于会话中:
SignIn signIn = null;
final Object userObject = RequestFactoryServlet.getThreadLocalRequest().getSession().getAttribute("auth");
if (userObject != null && userObject instanceof SignIn) {
signIn = (SignIn) userObject;
}
如果缺少此对象,则应取消请求并将用户重定向到登录页面。