【发布时间】:2011-07-06 15:06:52
【问题描述】:
我有一个home.jsf,它调用一个登录servlet,它查看数据库并在给定用户名和密码的情况下查询user 对象。然后我将user 对象保存到属性名称user 下的会话中,就像这样request.getSession().setAttribute("user", user);
protected void doPost(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
boolean remember = "true".equals(request.getParameter("remember"));
//Hashing the password with SHA-256 algorithms
password = hash(password);
HttpSession s = request.getSession(false);
if (s != null) {
logger.log(Level.INFO, "Id: {0}", s.getId());
}
User user = scholarEJB.findUserByUserNamePassword(username, password);
try {
if (user != null) {
request.login(username, password);
request.getSession().setAttribute("user", user);
if (remember) {
String uuid = UUID.randomUUID().toString();
UserCookie uc = new UserCookie(uuid, user.getId());
scholarEJB.persist(uc);
Helper.addCookie(response, Helper.COOKIE_NAME, uuid, Helper.COOKIE_AGE);
}else{
//If the user decide they dont want us to remember them
//anymore, delete any cookie associate with this user off
//the table
scholarEJB.deleteUserCookie(user.getId());
Helper.removeCookie(response, Helper.COOKIE_NAME);
}
response.sendRedirect("CentralFeed.jsf");
}else{
response.sendRedirect("LoginError.jsf");
}
} catch (Exception e) {
response.sendRedirect("LoginError.jsf");
}
然后我有一个映射到我所有安全页面的文件管理器,它将尝试从会话中检索用户对象,否则,将我重定向到 home.jsf 以再次登录
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession s = request.getSession(false);
if (s != null) {
logger.log(Level.INFO, "Id Before: {0}", s.getId());
}
User user = (User) request.getSession().getAttribute("user");
s = request.getSession(false);
if (s != null) {
logger.log(Level.INFO, "Id After: {0}", s.getId());
}
if (user == null) {
String uuid = Helper.getCookieValue(request, Helper.COOKIE_NAME);
if (uuid != null) {
user = scholarEJB.findUserByUUID(uuid);
if (user != null) {
request.getSession().setAttribute("user", user); //Login
Helper.addCookie(response, Helper.COOKIE_NAME, uuid, Helper.COOKIE_AGE);
} else {
Helper.removeCookie(response, Helper.COOKIE_NAME);
}
}
}
if (user == null) {
response.sendRedirect("home.jsf");
} else {
response.setHeader("Cache-Control", "no-cache, no-store, must-revalidate"); // HTTP 1.1.
response.setHeader("Pragma", "no-cache"); // HTTP 1.0.
response.setDateHeader("Expires", 0); // Proxies.
chain.doFilter(req, res);
}
现在,正如您在此处看到的,我也操作了一些 Cookie,但只有当我检查 remember me 时才会发生这种情况。所以现在我在CentralFeed.jsf,但是我从这里发送的任何请求都会带回home.jsf 再次登录。我浏览了一个调试器,所以当我第一次登录时,第一次进入过滤器时,我成功地从request.getSession().getAttribute("user"); 的会话中检索了user 对象。但在那之后,当我回到过滤器中时,我不再使用会话属性user。我在 web.xml 中将会话超时设置为 30 分钟
<session-config>
<session-timeout>
30
</session-timeout>
</session-config>
编辑
现在当我打印出请求之间的会话 ID 时,实际上是不同的会话 ID,但我不知道为什么?请帮忙。
EDIT2
@BalusC:实际上我确实使会话无效。那时,您向我展示了如何在用户登录其他地方时强制注销 (http://stackoverflow.com/questions/2372311/jsf-how-to-invalidate-an-user-session-when-he-logs-两次使用相同的凭据)。所以在用户实体里面我有这个
@Entity
public class User implements Serializable, HttpSessionBindingListener {
@Transient
private static Map<User, HttpSession> logins = new HashMap<User, HttpSession>();
@Override
public void valueBound(HttpSessionBindingEvent event) {
HttpSession session = logins.remove(this);
if (session != null) {
session.invalidate(); //This is where I invalidate the session
}
logins.put(this, event.getSession());
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
logins.remove(this);
}
}
在valueBound 方法中,我确实使会话无效,当我将其注释掉时,一切正常。我浏览了调试器,这就是发生的事情。当我第一次登录时,LoginServlet 会捕获它。然后request.getSession().setAttribute("user", user); 行调用valueBound 方法。然后调用了过滤器,chain.doFilter(req, res); 行再次调用了valueBound 方法,这一次,session 不为空,所以它进入了 if 和 session.invalidate。我将 session.invalidate 注释掉,它可以工作。但是您可能已经猜到了,当用户在其他地方登录时,我无法强制注销。你看到这个 BalusC 的明显解决方案了吗?
【问题讨论】:
标签: java session jakarta-ee glassfish glassfish-3