spring security3教程系列--如何踢出用户

  1. 本文章摘编、转载需要注明来源 http://write.blog.csdn.net/postedit/8572467  

对于spring security我个人是比较喜欢的一个安全框架,我们的系统中一般需要提供强制将用户踢出的功能,这个功能security也有提供,

首先我们要操作需要获取sessionRegistry中认证用户的所有SessionInformation,然后逐个调用SessionInformation里的expireNow()方法,然后ConcurrentSessionFilter

就会执行用户登录注销的功能;对于这个sessionRegistry.removeSessionInformation(sessionInformation
                    .getSessionId());我不知道是不是我的用法不对,调用了也不会强制注销用户的session,因为官方源代码中说调用removeSessionInformation的时候会让session的监听器响应到,但是我是没成功(望使用这个方式成功的朋友留言告诉下我);下面我们就看为什么调用SessionInformation里的expireNow()方法就能注销用户

[java]  view plain copy
  1. /** 
  2.      * 把当前用户踢出系统 
  3.      */  
  4.     public void shotOff() {  
  5.         List<SessionInformation> sessionInformations = sessionRegistry  
  6.                 .getAllSessions(SpringSecurityManager.getAuthentication()  
  7.                         .getPrincipal(), false);  
  8.         for (SessionInformation sessionInformation : sessionInformations) {  
  9.             sessionInformation.expireNow();  
  10.   
  11.             // sessionRegistry.removeSessionInformation(sessionInformation  
  12.                     .getSessionId());  
  13.   
  14.         }  
  15.     }  

我们来看下SessionInformation的源码

[java]  view plain copy
  1. private Date lastRequest;  
  2.    private final Object principal;  
  3.    private final String sessionId;  
  4.    private boolean expired = false;  
  5.   
  6.    //~ Constructors ===================================================================================================  
  7.   
  8.    public SessionInformation(Object principal, String sessionId, Date lastRequest) {  
  9.        Assert.notNull(principal, "Principal required");  
  10.        Assert.hasText(sessionId, "SessionId required");  
  11.        Assert.notNull(lastRequest, "LastRequest required");  
  12.        this.principal = principal;  
  13.        this.sessionId = sessionId;  
  14.        this.lastRequest = lastRequest;  
  15.    }  
  16.   
  17.    //~ Methods ========================================================================================================  
  18.   
  19.    public void expireNow() {  
  20.        this.expired = true;  
  21.    }  
  22.   
  23.    public Date getLastRequest() {  
  24.        return lastRequest;  
  25.    }  
  26.   
  27.    public Object getPrincipal() {  
  28.        return principal;  
  29.    }  
  30.   
  31.    public String getSessionId() {  
  32.        return sessionId;  
  33.    }  
  34.   
  35.    public boolean isExpired() {  
  36.        return expired;  
  37.    }  
  38.   
  39.    /** 
  40.     * Refreshes the internal lastRequest to the current date and time. 
  41.     */  
  42.    public void refreshLastRequest() {  
  43.        this.lastRequest = new Date();  
  44.    }  

看到的是调用expireNow方法时候会将属性expired设置为true;


然后我们来看下需要处理的ConcurrentSessionFilter过滤器的源码

[java]  view plain copy
  1. private SessionRegistry sessionRegistry;  
  2. private String expiredUrl;  
  3. private LogoutHandler[] handlers = new LogoutHandler[] {new SecurityContextLogoutHandler()};  
  4. private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();  
  5.   
  6. //~ Methods ========================================================================================================  
  7.   
  8.   
  9. /** 
  10.  * @deprecated Use constructor which injects the <tt>SessionRegistry</tt>. 
  11.  */  
  12. public ConcurrentSessionFilter() {  
  13. }  
  14.   
  15. public ConcurrentSessionFilter(SessionRegistry sessionRegistry) {  
  16.     this(sessionRegistry, null);  
  17. }  
  18.   
  19. public ConcurrentSessionFilter(SessionRegistry sessionRegistry, String expiredUrl) {  
  20.     this.sessionRegistry = sessionRegistry;  
  21.     this.expiredUrl = expiredUrl;  
  22. }  
  23.   
  24. @Override  
  25. public void afterPropertiesSet() {  
  26.     Assert.notNull(sessionRegistry, "SessionRegistry required");  
  27.     Assert.isTrue(expiredUrl == null || UrlUtils.isValidRedirectUrl(expiredUrl),  
  28.             expiredUrl + " isn't a valid redirect URL");  
  29. }  
  30.   
  31. public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)  
  32.         throws IOException, ServletException {  
  33.     HttpServletRequest request = (HttpServletRequest) req;  
  34.     HttpServletResponse response = (HttpServletResponse) res;  
  35.   
  36.     HttpSession session = request.getSession(false);  
  37.   
  38.     if (session != null) {  
  39.         SessionInformation info = sessionRegistry.getSessionInformation(session.getId());  
  40.   
  41.         if (info != null) {  
  42.             if (info.isExpired()) {  
  43.                 // Expired - abort processing  
  44.                 doLogout(request, response);  
  45.   
  46.                 String targetUrl = determineExpiredUrl(request, info);  
  47.   
  48.                 if (targetUrl != null) {  
  49.                     redirectStrategy.sendRedirect(request, response, targetUrl);  
  50.   
  51.                     return;  
  52.                 } else {  
  53.                     response.getWriter().print("This session has been expired (possibly due to multiple concurrent " +  
  54.                             "logins being attempted as the same user).");  
  55.                     response.flushBuffer();  
  56.                 }  
  57.   
  58.                 return;  
  59.             } else {  
  60.                 // Non-expired - update last request date/time  
  61.                 sessionRegistry.refreshLastRequest(info.getSessionId());  
  62.             }  
  63.         }  
  64.     }  
  65.   
  66.     chain.doFilter(request, response);  
  67. }  
  68.   
  69. protected String determineExpiredUrl(HttpServletRequest request, SessionInformation info) {  
  70.     return expiredUrl;  
  71. }  
  72.   
  73. private void doLogout(HttpServletRequest request, HttpServletResponse response) {  
  74.     Authentication auth = SecurityContextHolder.getContext().getAuthentication();  
  75.   
  76.     for (LogoutHandler handler : handlers) {  
  77.         handler.logout(request, response, auth);  
  78.     }  
  79. }  
  80.   
  81. /** 
  82.  * @deprecated use constructor injection instead 
  83.  */  
  84. @Deprecated  
  85. public void setExpiredUrl(String expiredUrl) {  
  86.     this.expiredUrl = expiredUrl;  
  87. }  
  88.   
  89. /** 
  90.  * @deprecated use constructor injection instead 
  91.  */  
  92. @Deprecated  
  93. public void setSessionRegistry(SessionRegistry sessionRegistry) {  
  94.     this.sessionRegistry = sessionRegistry;  
  95. }  
  96.   
  97. public void setLogoutHandlers(LogoutHandler[] handlers) {  
  98.     Assert.notNull(handlers);  
  99.     this.handlers = handlers;  
  100. }  
  101.   
  102. public void setRedirectStrategy(RedirectStrategy redirectStrategy) {  
  103.     this.redirectStrategy = redirectStrategy;  
  104. }  

很明显代码中有遇到if (info.isExpired())逻辑判断,这个时候如果表达式的值为true就会执行里面的doLogout方法,而这个方法里面就会调用我们配置的注销监听器,当前用户在之前认证成功后的状态也会失效了


然后看下xml里怎么配置

[java]  view plain copy
  1. <!-- SESSION管理 -->  
  2.     <bean id="sessionRegistry"  
  3.         class="org.springframework.security.core.session.SessionRegistryImpl" />  
  4.   
  5.     <bean id="concurrentSessionFilter"  
  6.         class="org.springframework.security.web.session.ConcurrentSessionFilter">  
  7.         <property name="sessionRegistry" ref="sessionRegistry" />  
  8.         <property name="expiredUrl" value="/apply/skip/restimeout.html" />  
  9.         <property name="logoutHandlers">  
  10.             <list>  
  11.                 <ref local="logoutHandler" />  
  12.             </list>  
  13.         </property>  
  14.     </bean>  
  15.       
  16.     <!-- 注销监听器  -->  
  17.     <bean id="logoutHandler"  
  18.         class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler">  
  19.         <property name="InvalidateHttpSession" value="true" />  
  20.     </bean>  

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值