我需要一点关于JSF(2.2.6)的方向理解会话。我试图找到一些文档,但仍然缺少一些东西。
我有一个@RequestScoped登录bean,它在会话映射中保存参数,以供其他会话作用域支持bean参考。他们通过PostConstruct方法获取用户信息,一切都很顺利。
但是,当使用多个窗口或用户没有注销并直接返回登录页面时,逻辑会失败。JSF将其视为相同的会话,并且不会调用@ postconstruct。
我很确定我可以使会话无效,但这并不能解决来自不同浏览器窗口的多个用户的问题。
任何指导或参考网站将不胜感激。
提前感谢!约翰。
会话必须是相同的每个浏览器窗口,唯一的例外是使用匿名模式:即chrome的行为就像有两个浏览器在同一时间打开。
另一种有多个会话的方法是使用不同的服务器名:http://localhost:8080/app
和http://127.0.0.1:8080/app
不能共享一个会话。
然而会话从不重叠。
你的问题,如果我理解正确,是当一个登录的用户访问登录页面和重新登录,保留他的旧会话,这就是为什么会话bean不是postconstruct再次(独立于窗口使用)。
一般的解决方案是禁止登录用户访问登录页面。通常,当用户重新登录而没有事先注销时,容器会抛出一个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的@ postconstruct,而是使用@ManagedProperty,这样OperationBean就包含了一个总是最新的对user的引用,而不必担心多次重新登录。