让以下类成为会话范围的CDI托管bean。
@Named
@SessionScoped
public class SessionUtils implements Serializable
{
private Map<String, Object>sessionMap;
private static final long serialVersionUID=1l;
public SessionUtils() {}
@PostConstruct
private void init() {
sessionMap=new HashMap<String, Object>();
}
public Map<String, Object> getSessionMap() {
return sessionMap;
}
}
地图用于存储用户特定信息。
我正在使用JAAS进行身份验证。登录Filter
。它的骨架如下所示。
@WebFilter(filterName = "SecurityCheck", urlPatterns = {"/WEB-INF/jaas/*"}, dispatcherTypes = {DispatcherType.REQUEST, DispatcherType.FORWARD})
public final class SecurityCheck implements Filter
{
@Inject
private UserBeanLocal userService;
@Inject
private SessionUtils sessionUtils;
public SecurityCheck() {}
private void doBeforeProcessing(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
String userName = request.getParameter("userName");
request.login(userName != null ? userName.trim() : "", request.getParameter("password"));
}
private void doAfterProcessing(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
Map<String, Object> sessionMap = sessionUtils.getSessionMap();
if (request.isUserInRole("ROLE_ADMIN")) {
UserTable userTable = userService.setLastLogin(request.getParameter("userName"));
userTable.setPassword(null);
//sessionMap.put("user", userTable);
request.getSession().setAttribute("newUser", new User());
response.sendRedirect(request.getContextPath() + "/admin_side/Home.xhtml");
}
//else {Repeat for other authorities}
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String userName = httpServletRequest.getParameter("userName");
HttpServletResponse httpServletResponse = ((HttpServletResponse) response);
try {
doBeforeProcessing(httpServletRequest, httpServletResponse);
} catch (ServletException e) {
httpServletResponse.sendRedirect(httpServletRequest.getContextPath() + "/utility/LoginError.xhtml");
return;
}
chain.doFilter(request, response);
doAfterProcessing(httpServletRequest, httpServletResponse);
}
}
我需要调用以下HttpSessionBindingListener
public final class User implements HttpSessionBindingListener {
private static final Map<UserTable, HttpSession> logins = new HashMap<UserTable, HttpSession>();
@Override
public void valueBound(HttpSessionBindingEvent event) {
System.out.println("valueBound() called.");
}
@Override
public void valueUnbound(HttpSessionBindingEvent event) {
System.out.println("valueUnbound() called.");
}
}
只有在沿着以下行使用代码时才会调用重写的方法。
request.getSession().setAttribute("newUser", new User()); //Or remove
但如果将User
的实例简单地存储到会话映射中(在该CDI bean中),则不会调用它们。
sessionMap.put("newUser", new User());
在JAAS / CDI中还有其他方法来处理相同的问题 - 模拟HttpSessionBindingListener
吗?
我想要做的是:如果用户忘记退出,则应在下次尝试登录时删除(之前仍处于活动状态)会话。
另外一件事:UserTable
(不是User
- 它只是一个例子。)是一个实际的JPA实体类。需要在该JPA实体上实现HttpSessionBindingListener
,这反过来又要求javax.servlet
包中对服务层的额外依赖,从而不必要地增加模块之间的耦合。
这可以被隔离,以便HttpSessionBindingListener
可以在Web层上实现(无论JPA实体类是什么 - UserTable
并仍然为该类服务,即{{1}的实例当UserTable
的{{1}}实例从valueBound()
移除,被另一个会话属性替换为valueUnbound()
时,会调用UserTable
方法... HttpSession
会话本身被破坏/无效)?我希望在高级Java EE中有一些方法。
问题标题不应该如此有意义。我会在以后编辑它,当我设想一个更有意义的标题,或者你可以在那之前自愿编辑它,如果你愿意的话。
答案 0 :(得分:0)
据我了解,问题是关注,为什么HttpSessionBindingListener
仅在您致电request.getSession()
时被调用?
只有在调用request.getSession()
时才会创建会话,因此会调用侦听器。
因此,您需要调用该方法才能启动会话,或者如果您在请求期间稍后调用该会话,则会启动该方法。
顺便说一句,将HttpSession
存储在静态变量中是不好的做法,如果你愿意忘记&#34;它可能会导致内存泄漏。删除它。
为了实现您尝试做的事情,我只在会话监听器中存储一组静态request.getSession().getId()
。在过滤器中,我会检查该集合是否具有id
,因此您将获得现有会话或创建新会话。
或者仍然存储在地图中,如果您确实需要知道会话属于哪个用户。
答案 1 :(得分:0)
如果用户忘记退出,则(先前仍处于活动状态)会话 应该在他/她下次尝试登录时删除。
我通常做的就是简单地丢弃&#34;当前&#34;渲染登录页面时的会话:
request.getSession().invalidate();
换句话说,进入登录页面意味着退出当前会话。