i am using spring security v3.1.4. what i want to achieve is to have an admin be able to log out a regular user (invalidate his session). a user can only log in once at any given time, but if he forgets to log out, then when he attempts to log in from another location, he won't be able to log in. so he'll put in a ticket to the admin, and the admin will invalidate all his previously logged in sessions (hopefully there's just one).
in my web.xml i have the following defined.
<listener>
<listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
</listener>
in my spring security xml i have the following defined.
<session-management invalid-session-url="/home">
<concurrency-control max-sessions="1" error-if-maximum-exceeded="true" session-registry-ref="sessionRegistry"/>
</session-management>
<beans:bean id="sessionRegistry" class="org.springframework.security.core.session.SessionRegistryImpl"/>
i then have a rest-like controller to perform the logging out.
@Controller
@RequestMapping("/api/admin")
public class RestAdminController {
static final Set<SimpleGrantedAuthority> AUTHS = new HashSet<>();
static {
AUTHS.add(new SimpleGrantedAuthority("ROLE_USER"));
}
@Autowired
private SessionRegistry sessionRegistry;
@RequestMapping("/user/logout");
public @ResponseBody String logout(@RequestBody Account account) {
User user = new User(account.getUsername(), "", AUTHS);
List<SessionInformation> infos = sessionRegistry.getAllSessions(u, false);
for(SessionInformation info : infos) {
info.expireNow(); //expire the session
sessionRegistry.removeSessionInformation(info.getSessionId()); //remove session
}
return "ok";
}
}
this code "kinda" works when i test it from the same computer. let's say we have a user, USER_A, and an administrator, ADMIN_A.
however, USER_A is now logged in twice, once in chrome and once in firefox.
any idea on approaches on how to completely invalidate/destroy USER_A's first/previous login sessions such that if he tries to access protected pages spring security will know, "hey this guy's session is invalid or expired, send him to the login page" ?
any help is appreciated. thanks.
It looks like you've almost got it, but I think the problem is that you are removing the information prematurely from the SessionRegistry
. The ConcurrentSessionFilter performs a check on the current session when a user makes a request, and at this point, it logs out an expired session and invalidates it. Since you have already removed the information for that session, it won't find it and will do nothing.
Try removing the line:
sessionRegistry.removeSessionInformation(info.getSessionId());
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With