自定义cas客户端核心过滤器authenticationFilter

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义cas客户端核心过滤器authenticationFilter相关的知识,希望对你有一定的参考价值。

自定义cas客户端核心过滤器AuthenticationFilter

         关于cas客户端的基本配置这里就不多说了,不清楚的可以参考上一篇博文:配置简单cas客户端。这里是关于cas客户端实现动态配置认证需要开发说明。

         往往业务系统中有些模块或功能是可以不需要登录就可以访问的,但是添加了cas客户端之后,通过cas客户端filter中的url-pattern来设置需要过滤的url,有时根本无法满足实际业务的需求,这里笔者就通过对cas客户端中源码的阅读,和对认证流程的理解,对cas客户端做了些改动,来实现动态配置cas客户端认证范围。

         下面是cas认证的核心配置,其中AuthenticationFilter过滤器为cas客户端核心过滤,下面的url-pattern是配置需要过滤的url,如果我们能编写该过滤器,我们就可以实现动态配置cas客户端的过滤url了。

 

[html] view plain copy
 
  1. <!-- cas统一认证  -->  
  2.  <filter>  
  3.     <filter-name>CASFilter</filter-name>  
  4.     <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>  
  5.     <init-param>  
  6.         <param-name>casServerLoginUrl</param-name>  
  7.         <param-value>http://localhost:8080/casServer3/login</param-value>  
  8.     </init-param>  
  9.     <init-param>  
  10.         <param-name>serverName</param-name>  
  11.         <param-value>http://localhost:8080</param-value>  
  12.     </init-param>  
  13.   </filter>  
  14.   <filter-mapping>  
  15.     <filter-name>CASFilter</filter-name>  
  16.     <url-pattern>/*</url-pattern>  
  17.   </filter-mapping>    
  18.   <filter>  
  19.     <filter-name>CAS Validation Filter</filter-name>  
  20.     <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>  
  21.     <init-param>  
  22.         <param-name>casServerUrlPrefix</param-name>  
  23.         <param-value>http://localhost:8080/casServer3</param-value>  
  24.     </init-param>  
  25.     <init-param>  
  26.         <param-name>serverName</param-name>  
  27.         <param-value>http://localhost:8080</param-value>  
  28.     </init-param>  
  29.   </filter>  
  30.   <filter-mapping>  
  31.     <filter-name>CAS Validation Filter</filter-name>  
  32.     <url-pattern>/*</url-pattern>  
  33.   </filter-mapping>  

 

 

思路:将配置中指向的核心过滤器,指向自己定义的过滤器,将源码中核心过滤器AuthenticationFilter的代码复制拷贝到该自定义过滤器中,然后在该过滤器中添加自己的过滤规则。

步骤:

1.配置并启动cas服务端,具体配置可以参考博文:搭建简单的cas认证服务

2.新建一个web项目,然后添加cas客户端配置,具体配置可以参考博文:配置简单cas客户端

3.导入cas客户端核心jar的源码到该web项目中,源码在cas客户端下载zip包中就有,一般为cas-client-core文件夹

4.在项目的src中新建类AuthenticationFilter,继承org.jasig.cas.client.util.AbstractCasFilter,打开web.xml文件,找到找到cas核心过滤器的配置项CASFilter,Ctrl+左键,点击进入org.jasig.cas.client.authentication.AuthenticationFilter类中,复制类里面的全部代码到自定义的AuthenticationFilter类中。修改web.xml中cas核心过滤器配置项CASFilter中的配置,将filter-class指向刚才自定义的AuthenticationFilter类,同时在该过滤器中添加<init-param>配置。如下

 

[html] view plain copy
 
  1. <filter>  
  2.     <filter-name>CASFilter</filter-name>  
  3.     <filter-class>com.supre.filter.AuthenticationFilter</filter-class>  
  4.     <init-param>  
  5.         <param-name>casServerLoginUrl</param-name>  
  6.         <param-value>http://localhost:8080/casServer3/login</param-value>  
  7.     </init-param>  
  8.     <init-param>  
  9.         <param-name>serverName</param-name>  
  10.         <param-value>http://localhost:8080</param-value>  
  11.     </init-param>  
  12.     <init-param>  
  13.         <param-name>excludePaths</param-name>  
  14.         <param-value>.*[/,\\]rest[/,\\].*</param-value>  
  15.     </init-param>  
  16.   </filter>  
  17.   <filter-mapping>  
  18.     <filter-name>CASFilter</filter-name>  
  19.     <url-pattern>/*</url-pattern>  
  20.   </filter-mapping>   

 

 

说明:

1其中param-name为参数名,这个在过滤器初始化中需要根据该名字来取param-value中的值

2其中param-value的值可以根据需要在filter中制定自己的规则,笔者这里是正则表达式

 

5.在自定义的AuthenticationFilter中添加自己的代码,来实现认证范围的控制,代码如下:

[java] view plain copy
 
  1. package com.supre.filter;  
  2.   
  3. import java.io.IOException;  
  4.   
  5. import javax.servlet.FilterChain;  
  6. import javax.servlet.FilterConfig;  
  7. import javax.servlet.ServletException;  
  8. import javax.servlet.ServletRequest;  
  9. import javax.servlet.ServletResponse;  
  10. import javax.servlet.http.HttpServletRequest;  
  11. import javax.servlet.http.HttpServletResponse;  
  12. import javax.servlet.http.HttpSession;  
  13.   
  14. import org.jasig.cas.client.authentication.DefaultGatewayResolverImpl;  
  15. import org.jasig.cas.client.authentication.GatewayResolver;  
  16. import org.jasig.cas.client.util.AbstractCasFilter;  
  17. import org.jasig.cas.client.util.CommonUtils;  
  18. import org.jasig.cas.client.validation.Assertion;  
  19. /** 
  20.  * 为了方便控制filter,自定义了统一认证过滤器AuthenticationFilter 
  21.  * @author Administrator 
  22.  * 
  23.  */  
  24. public class AuthenticationFilter extends AbstractCasFilter{  
  25.      /** 
  26.      * The URL to the CAS Server login. 
  27.      */  
  28.     private String casServerLoginUrl;  
  29.   
  30.     /** 
  31.      * Whether to send the renew request or not. 
  32.      */  
  33.     private boolean renew = false;  
  34.   
  35.     /** 
  36.      * Whether to send the gateway request or not. 
  37.      */  
  38.     private boolean gateway = false;  
  39.     /** 
  40.      * 添加属性,这里用来存放不过滤地址正则表达式,可以根据自己需求定制---1 
  41.      */  
  42.     private String excludePaths;  
  43.       
  44.     private GatewayResolver gatewayStorage = new DefaultGatewayResolverImpl();  
  45.   
  46.     protected void initInternal(final FilterConfig filterConfig) throws ServletException {  
  47.         if (!isIgnoreInitConfiguration()) {  
  48.             super.initInternal(filterConfig);  
  49.             setCasServerLoginUrl(getPropertyFromInitParams(filterConfig, "casServerLoginUrl", null));  
  50.             log.trace("Loaded CasServerLoginUrl parameter: " + this.casServerLoginUrl);  
  51.             setRenew(parseBoolean(getPropertyFromInitParams(filterConfig, "renew", "false")));  
  52.             log.trace("Loaded renew parameter: " + this.renew);  
  53.             setGateway(parseBoolean(getPropertyFromInitParams(filterConfig, "gateway", "false")));  
  54.             log.trace("Loaded gateway parameter: " + this.gateway);  
  55.   
  56.             final String gatewayStorageClass = getPropertyFromInitParams(filterConfig, "gatewayStorageClass", null);  
  57.   
  58.             if (gatewayStorageClass != null) {  
  59.                 try {  
  60.                     this.gatewayStorage = (GatewayResolver) Class.forName(gatewayStorageClass).newInstance();  
  61.                 } catch (final Exception e) {  
  62.                     log.error(e,e);  
  63.                     throw new ServletException(e);  
  64.                 }  
  65.             }  
  66.             //自定义添加代码,用来读取web配置文件中excludes属性值 ---2  
  67.             excludePaths = getPropertyFromInitParams(filterConfig, "excludePaths", null);//filterConfig.getInitParameter("excludePaths");  
  68.             excludePaths = excludePaths.trim();  
  69.         }  
  70.     }  
  71.   
  72.     public void init() {  
  73.         super.init();  
  74.         CommonUtils.assertNotNull(this.casServerLoginUrl, "casServerLoginUrl cannot be null.");  
  75.     }  
  76. // url判断逻辑,这里大家可以根据自己需要来制订规则  
  77.     private boolean isExclude(String uri){  
  78.         boolean isInWhiteList = false;  
  79.         if(excludePaths!=null&& uri!=null){  
  80.             isInWhiteList = uri.matches(excludePaths);  
  81.         }  
  82.         return isInWhiteList;  
  83.     }  
  84.      
  85.       
  86.     public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {  
  87.         final HttpServletRequest request = (HttpServletRequest) servletRequest;  
  88.         final HttpServletResponse response = (HttpServletResponse) servletResponse;  
  89.         final HttpSession session = request.getSession(false);  
  90.         final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;  
  91.        // 该判断是自定义的对符合条件的url进行通过处理 ---3  
  92.         if(isExclude(request.getRequestURI())){  
  93.             filterChain.doFilter(request, response);  
  94.             return;  
  95.         }  
  96.           
  97.         if (assertion != null) {  
  98.             filterChain.doFilter(request, response);  
  99.             return;  
  100.         }  
  101.   
  102.         final String serviceUrl = constructServiceUrl(request, response);  
  103.         final String ticket = CommonUtils.safeGetParameter(request,getArtifactParameterName());  
  104.         final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);  
  105.   
  106.         if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {  
  107.             filterChain.doFilter(request, response);  
  108.             return;  
  109.         }  
  110.   
  111.         final String modifiedServiceUrl;  
  112.   
  113.         log.debug("no ticket and no assertion found");  
  114.         if (this.gateway) {  
  115.             log.debug("setting gateway attribute in session");  
  116.             modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);  
  117.         } else {  
  118.             modifiedServiceUrl = serviceUrl;  
  119.         }  
  120.   
  121.         if (log.isDebugEnabled()) {  
  122.             log.debug("Constructed service url: " + modifiedServiceUrl);  
  123.         }  
  124.   
  125.         final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);  
  126.   
  127.         if (log.isDebugEnabled()) {  
  128.             log.debug("redirecting to \"" + urlToRedirectTo + "\"");  
  129.         }  
  130.   
  131.         response.sendRedirect(urlToRedirectTo);  
  132.     }  
  133.   
  134.     public final void setRenew(final boolean renew) {  
  135.         this.renew = renew;  
  136.     }  
  137.   
  138.     public final void setGateway(final boolean gateway) {  
  139.         this.gateway = gateway;  
  140.     }  
  141.   
  142.     public final void setCasServerLoginUrl(final String casServerLoginUrl) {  
  143.         this.casServerLoginUrl = casServerLoginUrl;  
  144.     }  
  145.       
  146.     public final void setGatewayStorage(final GatewayResolver gatewayStorage) {  
  147.         this.gatewayStorage = gatewayStorage;  
  148.     }  
  149.       
  150. }  

说明:上面的例子笔者是想在web中配置不需要认证的url,通过正则表达式来判断,这里相关的规则可以根据自己需要来编写。

 

6.到这里就基本完成了,根据自己定义的规则来做测试,大家可以在项目中创建多个jsp或html文件,放在不同目录下(部分设计为通过,部分设计为不通过),然后在浏览器中直接访问这些文件,看是否被拦截而跳到认证见面,通过根据自己定义的规则判断修改是否成功。

以上是关于自定义cas客户端核心过滤器authenticationFilter的主要内容,如果未能解决你的问题,请参考以下文章

具有自定义外部表单和弹簧安全性的 CAS 身份验证

Cas客户端源码解析

cas有些请求路径不需要单点登录过滤器拦截

谷歌分析核心报告 API;或使用自定义维度过滤

CAS-5.3单点登录/退出客户端搭建(Springboot)

cas客户端流程详解(源码解析)--单点登录