Is there any way, with springSecurityService, to log someone else out?
(For example, if a regular user leaves for the day and forgets to logout, and the manager wants to log their account out.)
Is there any way, with springSecurityService, to log someone else out?
(For example, if a regular user leaves for the day and forgets to logout, and the manager wants to log their account out.)
I have done in my application where , A admin User can logged-out forcefully any user from the list of all users currently logged-in into the system.
I get all users those are currently logged-in into the system and send to the jsp where list of all logged-in users are shown to the Admin user.
@PreAuthorize("hasRole('Currently_Logged-In_Users')")
@RequestMapping(value = "/getLoggedInUsers", method = RequestMethod.POST)
@ResponseBody
public Map<String, List<?>> getLoggedInUsers(Map<String, Object> map ,Model model) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String userName = auth.getName();
List<Object> principals = sessionRegistry.getAllPrincipals();
List<UserInfo> usersInfoList = new ArrayList<UserInfo>();
for (Object principal: principals) {
if (principal instanceof UserInfo) {
if(!((UserInfo) principal).getUsername().equals(userName)){
for(SessionInformation sess :sessionRegistry.getAllSessions(principal, false)){
if(!sess.isExpired()){
usersInfoList.add((UserInfo) sess.getPrincipal());
}
}
}
}
}
Map<String, List<?>> loggedInUserMap = new HashMap<String, List<?>>();
loggedInUserMap.put("loggenInUsers",
usersInfoList);
return loggedInUserMap;
}
Now Admin user can select any user or multiple user by clicking on check box against the users. and call forced Logged-out action.
@PreAuthorize("hasRole('Currently_Logged-In_Users')")
@RequestMapping(value = "/logoutSelectedUsers", method = RequestMethod.POST)
@ResponseBody
public Map<String, String> forcedLoggedOut(@RequestParam("userList[]")ArrayList<String> userList ,Model model ,HttpServletRequest request ) {
Map<String,String> map= new HashMap<String,String>();
try{
String successMessage =null;
List<String> userCodeList = new ArrayList<String>();
for(String userCode :userList ){
userCodeList.add(userCode);
}
List<Object> principals = sessionRegistry.getAllPrincipals();
for (Object principal: principals) {
if (principal instanceof UserInfo) {
if(userCodeList.contains(((UserInfo) principal).getUsername())){
for(SessionInformation sess :sessionRegistry.getAllSessions(principal, false)){
sess.expireNow();
successMessage = "msg.loggedOutSuccessfully";
}
}
}
}
map.put("successmsg", successMessage);
}
catch(Exception e){
map.put("failmsg", "msg.notLoggedOut");
logger.error(e.toString(),e);
}
return map;
}
The springSecurityService itself does not have this capability.
However, nothing is stopping you from creating your own ServletFilter to track session ids and security principals and expose a controller and pages to invalidate the associated session with a login.
Here's how I do it.
Edit: The example below uses the webxml plugin. You can also edit web.xml directly. See this answer for setting the timeout.
// src/groovy/com/example/ExpiringSessionEventListener.groovy:
package com.example
import grails.util.Holders
import javax.servlet.http.HttpSessionListener
import javax.servlet.http.HttpSessionEvent
import org.springframework.security.core.context.SecurityContext
public class ExpiringSessionEventListener implements HttpSessionListener {
@Override
public void sessionCreated(HttpSessionEvent event) {
// Do some logging
}
@Override
public void sessionDestroyed(HttpSessionEvent event) {
SecurityContext securityContext = event.session.getAttribute("SPRING_SECURITY_CONTEXT")
if (securityContext) {
UserService userService = Holders.applicationContext.getBean("userService")
String userName = securityContext.authentication.principal.username
userService.userLoggedOut(userName, event.session.id, Boolean.TRUE)
}
}
}
// grails-app/services/com/example/UserService.groovy:
package com.example
import grails.plugin.springsecurity.annotation.Secured
class UserService {
@Secured(["ROLE_USER"])
def userLoggedOut(String userName, String sessionId, Boolean expired) {
User user = User.findByUsername(userName)
if (expired) {
// Do user cleanup stuff after expired session
} else {
// Do user cleanup stuff after clicking the logout button
}
}
}
Edit:
// grails-app/conf/WebXmlConfig.groovy:
webxml {
sessionConfig.sessionTimeout = 10 // minutes
listener.add = true
listener.classNames = [
"com.example.ExpiringSessionEventListener"
]
}