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.
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.
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 tofalse
.
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
Why Does This Gridbaglayout Not Appear as Planned
How to Convert .Pfx File to Keystore with Private Key
How Does the Jvm Ensure That System.Identityhashcode() Will Never Change
How to Use Readline() Method in Java
Using an Instance of an Object as a Key in Hashmap, and Then Access It with Exactly New Object
Java Switch Statement Multiple Cases
Found Shared References to a Collection Org.Hibernate.Hibernateexception
Guessing the Encoding of Text Represented as Byte[] in Java
Arraylist Contains Case Sensitivity
What Is the Benefit of Polymorphism Using Collection Interface to Create Arraylist Object
Java 8 Lambda Expression and First-Class Values
Collection Interface VS Arrays
In Java 8, Why Is the Default Capacity of Arraylist Now Zero
Writing Custom Kafka Serializer
Access Maven Properties Defined in the Pom