spring secrity 登出做一些操作

今天 项目需要用户退出的时候记录登出日志,修改用户的登录状态






	
	
	
		
		
		
		
		
        
       
        
       
        
        
        
		
		
	
	
	
	
	
		
		
		
	
	
	

	
		  
          
          
		
	

	
	  
      
          
      
   
      
          
     
    
    
       	
       	
       	
     
    
    
    
	
	
	
		
		
		
	

	
	
		
            
		
	
	

	
	
	


	
	


	
	
	
	
		
		
	



java 代码


package com.threeti.danfoss.base.handler;


import java.io.IOException;


import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.authentication.logout.SimpleUrlLogoutSuccessHandler;


import com.threeti.danfoss.base.constant.XaConstant;
import com.threeti.danfoss.base.entity.XaCmsUser;
import com.threeti.danfoss.base.repository.XaCmsUserRepository;
import com.threeti.danfoss.base.security.XaUserDetails;


public class MyLogoutSuccessHandler extends SimpleUrlLogoutSuccessHandler 
  implements LogoutSuccessHandler{
@Autowired
private XaCmsUserRepository xaCmsUserRepository;

@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException {
XaUserDetails user = (XaUserDetails) authentication.getPrincipal();

XaCmsUser u = 
xaCmsUserRepository.findByUserName(user.getUsername(),XaConstant.Status.valid);
u.setOnline(0);
xaCmsUserRepository.save(u);
super.onLogoutSuccess(request, response, authentication);
}


}



还有另外一种方式:下面的就是复制前面的东西。没有进行测试,先记录下来,有空进行测试:

这里是前辈的文章地址:http://www.111cn.net/jsp/J2ME/60099.htm

spring security的form-login提供了default-target-url作为登录成功后的跳转地址,唯独没有允许传递一个redirectUrl参数来作为成功后的跳转地址。
同样的logout标签提供了logout-success-url作为退出成功后的跳转地址,也没有提供允许传递redirectUrl参数来进行跳转。
本来打算自己实现和AdminAuthSuccessHandler和LogoutSuccessHandler来接收redirectUrl参数进行跳转的,结果查看spring security的代码无意间发现spring security居然提供了targetUrlParameter作为跳转地址的参数,只是Security Namespace没有相关的标签或属性。于是在读完跳转相关的代码之后自己写了以下配置。
注:如果直接允许传递redirectUrl作为跳转地址,会有一定的安全风险。在使用之前,确保redirectUrl可信。下面的这段配置有一定安全隐患。

 代码如下 复制代码

   
   
   
   
   
       
   


 

     

   

   
   

   

   
   

通过查看源码我们发现,SimpleUrlLogoutSuccessHandler继续了AbstractAuthenticationTargetUrlRequestHandler,同样的SavedRequestAwareAuthenticationSuccessHandler也是继承了AbstractAuthenticationTargetUrlRequestHandler,而在AbstractAuthenticationTargetUrlRequestHandler的handle方法里,我们发现它是通过determineTargetUrl()方法来决定Redirect地址的。

 代码如下 复制代码
public class SimpleUrlLogoutSuccessHandler extends AbstractAuthenticationTargetUrlRequestHandler
        implements LogoutSuccessHandler {
 
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
            throws IOException, ServletException {
        super.handle(request, response, authentication);
    }
 
}

通过分析determineTargetUrl我们得出以下结论:
①如果alwaysUseDefaultTargetUrl为true,则跳转地址始终为defaultTargetUrl
②如果targetUrlParameter不为null,则从request中targetUrlParameter指定的参数名获取跳转地址
③如果useReferer为true,并且前两步没有获取到跳转地址,则从请求头中的Referer获取跳转地址
④如果以上几步都为空,则使用设置的defaultTargetUrl作为跳转地址
⑤defaultTargetUrl的默认值是"/"
 
在最终跳转时,spring security使用一个RedirectStrategy策略来进行跳转,一般都是使用DefaultRedirectStrategy来进行跳转,你也可以实现自己的RedirectStrategy并配置在adminAuthSuccessHandler的bean定义中。
 
在刚开始的时候我们说过“如果直接允许传递redirectUrl作为跳转地址,会有一定的安全风险”。如果别人通过你的login或logout传递redirectUrl参数误导用户跳到了病毒木马网站,那这肯定是你的安全做的不够,为了安全我们,我们需要实现自己的SafeRedirectStrategy,如下所示,在跳转之前对URL进行了白名单校验。

 代码如下 复制代码
/**
 * 安全的RedirectStrategy,主要是判断跳转地址是否在白名单中
 * @author guoweiwei [email protected]
 *
 */
public class SafeRedirectStrategy implements RedirectStrategy {
 
    protected final Log logger = LogFactory.getLog(getClass());
 
    private boolean contextRelative;
 
    /**
     * Redirects the response to the supplied URL.
     *


     * If contextRelative is set, the redirect value will be the value after the request context path. Note
     * that this will result in the loss of protocol information (HTTP or HTTPS), so will cause problems if a
     * redirect is being performed to change to HTTPS, for example.
     */
    public void sendRedirect(HttpServletRequest request, HttpServletResponse response, String url) throws IOException {
        String redirectUrl = calculateRedirectUrl(request.getContextPath(), url);
         
 
        try {
            if(UrlUtils.isAbsoluteUrl(redirectUrl)){
                        redirectUrl = UrlUtil.buildRedirectLink(redirectUrl, false);
                    }
        } catch (Exception e) {
            throw new IOException("error redirect url", e);
        }
 
         
        redirectUrl = response.encodeRedirectURL(redirectUrl);
 
        if (logger.isDebugEnabled()) {
            logger.debug("Redirecting to '" + redirectUrl + "'");
        }
 
        response.sendRedirect(redirectUrl);
    }
 
    private String calculateRedirectUrl(String contextPath, String url) {
        if (!UrlUtils.isAbsoluteUrl(url)) {
            if (contextRelative) {
                return url;
            } else {
                return contextPath + url;
            }
        }
 
        // Full URL, including http(s)://
 
        if (!contextRelative) {
            return url;
        }
 
        // Calculate the relative URL from the fully qualified URL, minus the scheme and base context.
        url = url.substring(url.indexOf("://") + 3); // strip off scheme
        url = url.substring(url.indexOf(contextPath) + contextPath.length());
 
        if (url.length() > 1 && url.charAt(0) == '/') {
            url = url.substring(1);
        }
 
        return url;
    }
 
    /**
     * If true, causes any redirection URLs to be calculated minus the protocol
     * and context path (defaults to false).
     */
    public void setContextRelative(boolean useRelativeContext) {
        this.contextRelative = useRelativeContext;
    }
 
}

上面代码中UrlUtil为自己实现的一个Url处理工具,buildRedirectLink会对url做白名单校验。完了别忘了在servlet.xml的bean配置中加入safeRedirectStrategy。如下所示:

 代码如下 复制代码

   
   
   
 

   
 
     
     
     
 

   
 


你可能感兴趣的:(spring secrity 登出做一些操作)