您好
我目前正在玩Guice和@SessionScoped。为了更有意义,我决定构建一个(非常简单的)身份验证过程。
下面,我将解释我所做的每一步。然后我会问你一些问题。
[1] 我创建了一个代表一个人(访客或用户)的Identity类:
@SessionScoped
public class Identity implements Serializable
{
private String uid;
private String name;
public boolean isAuthenticate()
{
return uid != null;
}
public void logout()
{
this.uid = null;
}
/*Setters-Getters*/
}
[2] 接下来,我创建了一个登录用户的身份验证类:
public class Authentication
{
@Override
public Identity authenticate(String login, String password)
{
/*some code*/
Identity identity = new Identity();
identity.setUid(user.getId());
return identity;
}
}
[3] 然后,在我的Servlet中,我登录用户:
@RequestScoped
public class LoginAction
{
@Inject
Injector injector;
protected void login(HttpServletRequest req, HttpServletResponse resp)
{
Identity identity = injector.getInstance(Identity.class);
Authentication auth = new Authentication();
identity = auth.authenticate("login","password");
}
}
[4] 最后,我创建了一个过滤器,告诉我用户是否经过身份验证:
@Singleton
public class SecurityFilter implements Filter
{
@Inject
private Injector injector;
@Override
public void doFilter(ServletRequest request, ServletResponse response,FilterChain chain)
{
Identity identity = injector.getInstance(Identity.class);
if(identity.isAuthenticate())
{
System.err.println("USER");
}
else
{
System.err.println("GUEST");
}
chain.doFilter(request, response);
}
}
嗯,这段代码不起作用。我的身份的uid总是“空”。
让我们回答问题:
a - 首先,为什么我的代码不起作用?
b - @SessionScoped是否相当于在HttpSession中设置对象?
c - 如何在(http)会话中使Identity对象(仅限于它)无效?
d - 通常,在哪种情况下我们必须使用@SessionScoped?
感谢您的阅读,
等你的回答。
答案 0 :(得分:9)
[a]您将Identity
的新实例分配给LoginAction
中的本地变量,而不是替换Guice管理的实例。您可以通过填充Guice管理的现有uid
实例上的name
和Identity
字段来解决问题。
例如,而不是
identity = auth.authenticate("login","password");
你可以说:
Identity identity = injector.getInstance(Identity.class);
Authentication auth = new Authentication();
Identity authenticated = auth.authenticate("login","password");
identity.setUid(authenticated.getUid());
identity.setName(authenticated.getName());
有更简洁的方法可以做到这一点,但你明白了。
[b] / [d]这是正确的:@SessionScoped
相当于在HttpSession
中设置变量,这就是您要使用它的情况。对于需要在会话中唯一的对象,您需要它,但需要为每个请求提供。
[c]我不太清楚你的意思,但是如果你想根据用户是否登录而重定向到应用程序的不同位置,你的过滤器设计是一种常见的方法。
您可以进行一些改进:
SessionScoped
的{{1}}服务,并确保它在Identity
实例上同步。这样,如果用户快速连续发出两个请求,您将不会遇到并发问题。Identity
而不是注入Provider
(示例here)以将您的类与Guice分离。