How to Invalidate an User Session When He Logs Twice with the Same Credentials

How to invalidate an user session when he logs twice with the same credentials

The DB-independent approach would be to let the User have a static Map<User, HttpSession> variable and implement HttpSessionBindingListener (and Object#equals() and Object#hashCode()). This way your webapp will still function after an unforeseen crash which may cause that the DB values don't get updated (you can of course create a ServletContextListener which resets the DB on webapp startup, but that's only more and more work).

Here's how the User should look like:

public class User implements HttpSessionBindingListener {

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

// 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) {
sessionMap.put("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:

sessionMap.remove("user");

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

Java How to invalidate user session when he logs twice with same credential

The point about running the application on a cluster is more important and relevant than the absence of JSF.

The requirement imposed by the cluster on any solution is that the solution require the use of a shared storage that is accessible to all members of the cluster. There are are several possible solutions that account for this requirement:

  • Use a database to store the list of all currently logged in users (with an ID to identify their session; JSESSIONID could be used, but it is better to use an ID that is guaranteed to be unique across all members in the cluster). Even a combination of user ID and cluster member ID will do. This is the easiest, but it will require you to test how your code handles failover (you might have to update the entries in the database on session failover).
  • Use the application context (the ServletContext). This is a possible solution, but not recommended at all. Although the application context is bound to be kept up to date in all cluster members, there is a cost to keep the contents up to date (increased network traffic among cluster members).
  • Use a distributed caching solution like Terracotta or Coherence. This solution is almost the same as the previous one, except that the session "map" will not be managed in the ServletContext. Network traffic is bound to occur when updating the distributed cache.

Invalidate Session of a specific user

Is this a correct approach?

There are basically 2 ways.

  1. Store the HttpSession handle in the application scope by the user ID as key so that you can get a handle of it and invalidate it. This may work for a small web application running on a single server, but may not work on a web application running on a cluster of servers, depending on its configuration.

    I would only store it in another map in the application scope, not directly in the application scope like as you did, so that you can easier get an overview of all users and that you can guarantee that an arbitrary user ID won't clash with an existing application scoped managed bean name, for example.

  2. Add a new boolean/bit column to some DB table associated with the user which is checked on every HTTP request. If the admin sets it to true, then the session associated with the request will be invalidated and the value in the DB will be set back to false.


how do I clean up my application map?

You could use HttpSessionListener#sessionDestroyed() for this. E.g.

public void sessionDestroyed(HttpSessionEvent event) {
User user = (User) event.getSession().getAttribute("user");
if (user != null) {
Map<User, HttpSession> logins = (Map<User, HttpSession>) event.getSession().getServletContext().getAttribute("logins");
logins.remove(user);
}
}

How can I make sure that a user cannot login twice with the same account in PHP?

You can link the session id with the logged in user. Then look up if that user has a session id, if so destroy that session with that session id. Link the session name also. Then you can destroy the session cookie of that user.

setcookie($session_name, '', time()-3600, '/');

Invalidating session

I imagine the sessionId cookie will still be kept, but since this sessionId will not match any session object in the server's memory, it will be discarded by the server next time user tries to login again. On the server side it will be quite transparent, request.getSession() will return a new session object automatically.

How Invalidate users sessions when makes logout?

I would recommend you to have a look at SessionRegistry .You can check this here . There has been a discussion on this at Is it possible to invalidate a spring security session? . Check this out too

Spring sessions are stored as JsessionID cookies. Check here for a discussion on cookie removal.

The same query has been discussed at Invalid a session when user makes logout (Spring).



Related Topics



Leave a reply



Submit