Prevent multiple login using the same user name and password

If user close the browser without logout.

Particularly this case is hard and not reliable to detect. You could use the beforeunload event in Javascript, but you’re fully dependent on whether the browser has JS enabled and the particular browser supports this non-standard event (e.g. Opera doesn’t). That’s also one of the major reasons that I’d suggest to just logout the previously logged in user instead of preventing the login. That’s also more user-friendly and secure for the case that the user “forgot” to logout from the other computer.

Easiest way is to let the User have a static Map<User, HttpSession> variable and let it implement HttpSessionBindingListener (and Object#equals() and Object#hashCode()).

public class User implements HttpSessionBindingListener {

    // All logins.
    private static Map<User, HttpSession> logins = new HashMap<User, HttpSession>();

    // Normal properties.
    private Long id;
    private String username;
    // Etc.. Of course with public getters+setters.

    @Override
    public boolean equals(Object other) {
        return (other instanceof User) && (id != null) ? id.equals(((User) other).id) : (other == this);
    }

    @Override
    public int hashCode() {
        return (id != null) ? (this.getClass().hashCode() + id.hashCode()) : super.hashCode();
    }

    @Override
    public void valueBound(HttpSessionBindingEvent event) {
        HttpSession session = logins.remove(this);
        if (session != null) {
            session.invalidate();
        }
        logins.put(this, event.getSession());
    }

    @Override
    public void valueUnbound(HttpSessionBindingEvent event) {
        logins.remove(this);
    }

}

When you login the User as follows:

User user = userDAO.find(username, password);
if (user != null) {
    request.getSession.setAttribute("user", user);
} else {
    // Show error.
}

then it will invoke the valueBound() which will remove any previously logged in user from the logins map and invalidate the session.

When you logout the User as follows:

request.getSession().removeAttribute("user");

or when the session is timed out, then the valueUnbound() will be invoked which removes the user from the logins map.

Leave a Comment