如果上一个会话已处于活动状态(如果用户忘记注销),则使用 JAAS 将其除去



让以下类成为会话范围的 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实体类。HttpSessionBindingListener需要在该 JPA 实体上实现,这反过来又需要对 javax.servlet 包的服务层的额外依赖,从而不必要地增加模块之间的耦合。

是否可以将其隔离,以便可以在 Web 层上实现HttpSessionBindingListener(无论该 JPA 实体类如何 - UserTable并且仍然为该类提供服务,即当UserTable实例放入会话时,调用valueBound()方法...和valueUnbound(),当UserTable的实例从HttpSession中删除时,替换为另一个会话属性或会话本身被销毁/失效(?我希望在高级Java EE中有一些方法。

问题标题没有应有的意义。稍后,当我设想一个更有意义的标题时,我会编辑它,或者如果你愿意,你可以在那之前自愿编辑它。

我了解,问题如下,为什么只有当你打电话给request.getSession()时才调用HttpSessionBindingListener

仅当您调用request.getSession()会话时,才会创建会话,因此将调用侦听器。因此,您需要调用该方法才能启动会话,或者如果您稍后在请求期间调用它,它将启动。

顺便说一句,将HttpSession存储在静态变量中是一种不好的做法,如果您"忘记"删除它,可能会导致内存泄漏。

为了实现您要执行的操作,我将只在会话侦听器中存储一组静态request.getSession().getId()。在过滤器中,我会检查集合是否具有这样的id,因此您将获得现有会话或创建一个新会话。或者仍然存储在map中,如果你真的需要知道会话属于哪个用户。

如果用户忘记注销,(上一个仍处于活动状态(会话 应在他/她下次尝试登录时删除。

我通常做的是在呈现登录页面时简单地丢弃"当前"会话:

request.getSession().invalidate();

换句话说,转到登录页面意味着注销当前会话。

相关内容

  • 没有找到相关文章

最新更新