我有一个使用GWTP的应用程序,它严重依赖于Gin&吉斯。我的应用程序身份验证使用CurrentUserDto
来表示当前登录的用户,该用户绑定到Provider
并在需要的地方注入。
我的应用程序允许用户通过对照数据存储检查用户的电子邮件和密码来登录,如果匹配,则在用户的cookie中设置一个令牌,以表示已登录。到目前为止,这是非常基本的东西。。。
CurrentUserDtoProvider
检查客户端上的cookie,如果它存在并且仍然有效,则返回具有正确详细信息的CurrentUserDto
。
我的LoginPresenter
:
public class LoginPresenter extends Presenter<LoginPresenter.MyView, LoginPresenter.MyProxy> implements LoginUiHandlers
{
private CurrentUserDto currentUserDto;
public interface MyView extends View, HasUiHandlers<LoginUiHandlers>
{
}
@Title("Login")
@NoGatekeeper
@ProxyStandard
@NameToken(NameTokens.login)
public interface MyProxy extends ProxyPlace<LoginPresenter>
{
}
private DispatchAsync dispatchAsync;
private PlaceManager placeManager;
@Inject
public LoginPresenter(EventBus eventBus, MyView view, MyProxy proxy,
DispatchAsync dispatchAsync, PlaceManager placeManager,
CurrentUserDto currentUserDto)
{
super(eventBus, view, proxy, RevealType.Root);
this.dispatchAsync = dispatchAsync;
this.placeManager = placeManager;
this.currentUserDto = currentUserDto;
getView().setUiHandlers(this);
}
@Override
protected void onReveal()
{
if(currentUserDto.isLoggedIn())
{
System.out.println("User IS logged in - redirecting to main page");
PlaceRequest request = new PlaceRequest.Builder().nameToken(NameTokens.home).build();
placeManager.revealPlace(request, true);
}
else
{
System.out.println("User IS NOT logged in - showing login page");
// do nothing, we are already on the login page
}
}
@Override
public void onLoginClick(final String email, String password)
{
Window.alert("Client logging in as " + email + " with password " + password);
ClientLogin action = new ClientLogin(email, password);
dispatchAsync.execute(action, new AsyncCallbackImpl<ClientLoginResult>()
{
@Override
public void onReturn(ClientLoginResult result)
{
// set the cookie
Cookies.setCookie("usavtoken", result.getToken());
// here I would like to do this:
//placeManager.revealDefaultPlace()
// but instead I have to do this:
// browser refresh workaround, reloads whole app
String newURL = Window.Location.getHref();
Window.Location.assign(newURL);
}
});
}
}
当我的ClientLogin
操作返回验证令牌时,就会出现问题。参见上述onReturn()
方法。在这里,我想再次简单地运行onReveal()
中的代码,但由于CurrentUserDto
仍然表示用户未登录,登录页面留在屏幕上。
刷新整个GWT应用程序是我能够刷新CurrentUserDto
实体中的详细信息的唯一方法,该实体在用户登录之前被注入到登录页面中。最好的方法是什么?
是否有其他方法可以获得CurrentUserDto的新副本
是否有其他方法可以重新加载同一页面,从而导致Gin再次调用@Inject
我的构造函数
如果不清楚,请道歉。我对GIN/Gice不是很有经验。
您正在设置cookie并转发到不同的URL。对于GWT或GWTP,这是不必要的。不需要经典的回发心态。
使用页面上的@LoggedInGatekeep控制对登录/注销状态的访问。Cookie应在服务器请求身份验证时设置,并在注销请求时清除@Gin连接的LoggedInGatekeeper实现应该跟踪当前登录用户的用户对象(如果需要的话)
以下是我在应用程序中使用的步骤
打开(应用程序)页面加载
- 向服务器发出请求,我是否已经登录
- 如果已经登录,则获取当前用户对象(可以在1中返回)
- 在LoggedInGatekeeper中设置用户对象,并将登录状态设置为true
LoggedInGatekeeper现在将为您完成其余工作。如果他们正在请求一个内部页面,并且已经注销,它会将他们转发到指定的默认位置,通常是登录屏幕。
登录时
- 将凭据发送到服务器
- 如果有效,请在服务器上创建有效的用户会话并返回用户对象(与上面的2相同)
- 将用户对象和登录状态存储在LoggedInGatekeeper中
- 转发到您希望用户访问的下一个地点
注销时
- 向服务器发送请求
- 服务器使会话无效并清除cookie
- 清除LoggedInGatekeeper登录状态和用户对象
- 将用户转发到已注销的位置
因此,再次强调,甚至不需要触摸客户端的cookie。不要把你的客户和饼干联系在一起。Cookie会给每个请求增加开销,并将您的客户端和服务器代码结合起来。服务器知道如何处理会话,所以让它来处理它们。
您应该bind(CurrentUserDto.class).in(Singleton.class)
,并在onReturn
方法中设置currentUserDto.setLoggedIn(true)
。
不将CurrentUserDto
绑定为Singleton怎么样?那么,您应该在每个currentUserDtoProvider.get()
上获得一个新实例!
然后,您需要将CurrentUserDtoProvider
注入演示者中,因为他们是单身,不在CurrentUserDto
上保留引用,但在需要检查登录用户时始终调用currentUserDtoProvider.get()
。
顺便说一下,查看提供程序代码也会很有帮助。