如何使用Spring安全性以编程方式登出用户

我正在使用spring security v3.1.4。 我想要实现的是让管理员能够注销常规用户(使他的会话无效)。 用户只能在任何给定时间登录一次,但如果他忘记退出,那么当他尝试从其他位置登录时,他将无法登录。所以他会把票管理员和管理员将使他之前登录的所有会话无效(希望只有一个)。

在我的web.xml中,我有以下定义。

 org.springframework.security.web.session.HttpSessionEventPublisher  

在我的spring安全xml我有以下定义。

     

然后我有一个类似rest的控制器来执行注销。

 @Controller @RequestMapping("/api/admin") public class RestAdminController { static final Set 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 infos = sessionRegistry.getAllSessions(u, false); for(SessionInformation info : infos) { info.expireNow(); //expire the session sessionRegistry.removeSessionInformation(info.getSessionId()); //remove session } return "ok"; } } 

当我从同一台计算机上测试时,这段代码“kinda”有效。 假设我们有一个用户USER_A和一个管理员ADMIN_A。

  • USER_A使用chrome登录APP。
  • USER_A使用firefox登录APP。 他被拒绝是因为用户一次只能有1个登录会话。
  • ADMIN_A进入,并调用类似其余的服务(上面的代码)来“踢出”所有USER_A的会话。
  • USER_A现在可以使用firefox登录APP。

但是,USER_A现在已经登录两次,一次是在chrome中,一次是在firefox中。

  • 在chrome(第一次登录)中刷新USER_A的(弹簧安全保护的)页面不会强制他被重定向(到登录页面)。
  • 在firefox中刷新USER_A的受保护页面(第二次登录)也不会强制他被重定向。

关于如何完全无效/销毁USER_A的第一个/上一个登录会话的方法的任何想法,如果他试图访问受保护的页面,spring的安全性会知道,“嘿,这个人的会话无效或已过期,请将他发送到登录页面”?

任何帮助表示赞赏。 谢谢。

看起来你已经差不多了,但我认为问题在于你是否过早地从SessionRegistry中删除了这些信息。 当用户发出请求时, ConcurrentSessionFilter会对当前会话执行检查,此时,它会注销已过期的会话并使其无效。 由于您已经删除了该会话的信息,因此无法找到它并且什么都不做。

尝试删除该行:

 sessionRegistry.removeSessionInformation(info.getSessionId()); 

您只需要修改equals()hashCode() 。 您的代码稍后会运行。 这可能会有所帮助: http : //blog.trifork.com/2014/02/28/session-timeout-and-concurrent-session-control-with-spring-security-and-spring-mvc/