我需要一点方向来理解JSF(2.2.6)中的会话。我试图找到一些文档,但我仍然遗漏了一些东西。
我有一个@RequestScoped登录bean,它在会话映射中保存参数,供其他会话范围的后备bean参考。他们通过PostConstruct方法得到用户信息,一切都很好。
但是,当使用多个窗口或用户未注销并直接返回登录页面时,逻辑会失败。 JSF将此视为同一会话,并且不调用@PostConstructs。
我很确定我可以使会话无效,但这并不能解决来自不同浏览器窗口的多个用户的问题。
任何指导或参考网站都将受到赞赏。
提前致谢! 约翰
答案 0 :(得分:1)
会话对于每个浏览器窗口都是相同的,唯一的例外是使用匿名模式时:即chrome表现得像是同时打开两个浏览器。
拥有多个sesssions的另一种方法是使用不同的服务器名称:
http://localhost:8080/app
和http://127.0.0.1:8080/app
可能不会共享一个会话。
然而会话永远不会重叠。
你的问题,如果我理解正确,是当一个登录的用户访问登录页面并重新登录,保留他的旧会话,这就是为什么会话bean不再是PostConstructed(独立于使用的窗口)
一般解决方案是禁止访问已登录用户的登录页面。 通常,当用户在没有事先注销的情况下重新登录时,容器将抛出AlreadyAuthenticatedException或类似的事件。
简而言之,只是一个等待代码的初步示例:
@ManagedBean
@SessionScoped
public class UserBean implements Serializable
{
private static final long serialVersionUID = 1L;
private User user;
public boolean isLoggedIn()
{
return user != null;
}
public void login(String username, String password)
{
// maybe you want to check isLoggedIn() and either call logout() or throw an exception
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
request.login(username, password);
user = someDAO.loadFromDatabase(username);
}
public void logout()
{
// maybe you want to check isLoggedIn() and either throw an exception or do nothing
HttpServletRequest request = (HttpServletRequest) FacesContext.getCurrentInstance().getExternalContext().getRequest();
request.logout();
user = null;
// suggested for another scenario
// request.getSession().invalidate();
}
// getters and setters
}
和
@ManagedBean
@SessionScoped
public class OperationBean implements Serializable
{
private static final long serialVersionUID = 1L;
@ManagedProperty("#{userBean}")
private UserBean userBean;
public void execute()
{
if(!userBean.isLoggedIn())
{
FacesContext.getCurrentInstance().getExternalContext().redirect("login.jsf");
return;
}
User user = userBean.getUser();
// do something
}
// getters and setters
}
使用这种组合,而不是使用OperationBean的@PostContruct我使用了@ManagedProperty,因此OperationBean包含对用户的始终最新的引用,而不需要多次重新登录。