I currently detect if a user is logged out by searching for null attributes
That's also the normal approach. To check if an user is logged in, you should surely not check if the servletcontainer has created the session or not. This does not represent the logged-in user at all.
On login, just put the user model object in the session scope without checking if the container has created the session for you. In other words, just use getSession()
without boolean argument so that the container will autocreate if necessary, you need the session at this point anyway:
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String username = request.getParameter("username");
String password = request.getParameter("password");
User user = userService.find(username, password);
if (user != null) {
request.getSession().setAttribute("user", user);
response.sendRedirect(request.getContextPath() + "/home");
} else {
request.setAttribute("message", "Unknown login. Please retry.");
request.getRequestDispatcher("/WEB-INF/login.jsp").forward(request, response);
}
}
On access filtering, just check if the session attribute representing the logged-in user is present, you only use getSession(false)
here to avoid unnecessary session creation, otherwise for example searchbots would trigger session creation which is totally unnecessary:
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
HttpSession session = request.getSession(false);
User user = (session != null) ? (User) session.getAttribute("user") : null;
String loginURL = request.getContextPath() + "/login";
if (user == null && !request.getRequestURI().equals(loginURL)) {
response.sendRedirect(loginURL);
} else {
chain.doFilter(request, response);
}
}
On logout, make sure that you send a redirect after invalidate, because the current session is still available in the response of a forward.
@Override
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.getSession().invalidate();
response.sendRedirect(request.getContextPath() + "/login");
}