`
wbj0110
  • 浏览: 1550847 次
  • 性别: Icon_minigender_1
  • 来自: 上海
文章分类
社区版块
存档分类
最新评论

CAS 源码分析 (非proxy模式)

阅读更多

 

一、CAS 基本原理   (3,4,5,9.2,9.3是主要步骤)

第一次访问:
1. 浏览器   发起访问WebAPP 请求:  http://www.web.com/app
2. 客户端  AuthenticationFilter Filter 发现Session中无 Assertion,且URL中无 ticket 变量。生成 service url 变量,并重定向到:  https://www.cas-server.com/cas/login?service=http://www.web.com/app



3. CAS server  生成 Login ticket, service 对象,并展示 login 页面,默认提供 username / password 给用户验证。
4. CAS server 端,用户输入 username / password 验证,若通过则生成TGT,存入服务器段(默认为 Map 类型的 cache),同时将TGT id 作为 content创建 cookie 并发送到浏览器。
5. CAS server 端通过TGT 生成service ticket.  重定向到 http://www.web.com/app?ticket=ST-xxx

 

 

6. 客户端   访问 http://www.web.com/app?ticket=ST-xxx
7. 客户端   AuthenticationFilter Filter 发现URL中有 ticket, 跳过 AuthenticationFilter过滤器,到达 Cas20ProxyReceivingTicketValidationFilter过滤器。


8. 客户端 生成验证 service url:  http://www.web.com/app
9. 客户端   Cas20ProxyReceivingTicketValidationFilter 过滤器,使用6处的ticket 与8处的 service 作为参数验证。

  9.1  客户端 生成验证 servlet: https://www.cas-server.com/cas/serviceValidate?ticket=ST-xxx&service=http://www.web.com/app
  9.2  客户端 通过HttpClient访问 9.1 的 url
                注:AbstractUrlBasedTicketValidator.java line 207,如果是用CAS ptotocol验证,则第二个参数 ticket无用。
                得到如下形式的 response:

Java代码 复制代码 收藏代码
  1. 546 <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>   
  2. 547         <cas:authenticationSuccess>   
  3. 548                 <cas:user>jack</cas:user>   
  4. 549    
  5. 550    
  6. 551         </cas:authenticationSuccess>   
  7. 552 </cas:serviceResponse>  
546 <cas:serviceResponse xmlns:cas='http://www.yale.edu/tp/cas'>
547         <cas:authenticationSuccess>
548                 <cas:user>jack</cas:user>
549 
550 
551         </cas:authenticationSuccess>
552 </cas:serviceResponse>

   9.3  客户端 解析 response 字符串,生成 assertion (包含 username, validate info 等)

   9.4  客户端 设置 assertion 为 request 的 _const_cas_assertion_ 属性。

   9.5  客户端 如果设置了重定向属性,则重定向到 http://www.web.com/app  --  转步骤10

              否则继续执行以后的 filter,通过servlet 访问 http://www.web.com/app 服务,结束CAS的验证。

 

用户已成功登录,非第一次访问:

10. 客户端 通过重定向访问 http://www.web.com/app

11. 客户端 AuthenticationFilter Filter 发现 session 中有Assertion, 结束本过滤器,转移到下一个过滤器 Cas20ProxyReceivingTicketValidationFilter.

12. 客户段 Cas20ProxyReceivingTicketValidationFilter 发现 本次访问的URL 无 ticket,结束本次过滤,转移到下一个过滤器,继续执行以后的 filter,通过servlet 访问 http://www.web.com/app 服务。

 

二 源码解析

 

1. 客户端 web.xml  片段:

 

Xml代码 复制代码 收藏代码
  1. ...   
  2.   
  3. <filter>  
  4.           <filter-name>CAS Authentication Filter</filter-name>  
  5.           <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>  
  6.           <init-param>  
  7.                 <param-name>casServerLoginUrl</param-name>  
  8.                 <param-value>https://www.colorcc.com:8443/cas/login</param-value>  
  9.           </init-param>  
  10.           <init-param>  
  11.                 <param-name>serverName</param-name>  
  12.                 <param-value>http://localhost:8080</param-value>  
  13.           </init-param>  
  14.     </filter>  
  15.     <filter>  
  16.           <filter-name>CAS Validation Filter</filter-name>  
  17.           <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>  
  18.           <init-param>  
  19.                 <param-name>casServerUrlPrefix</param-name>  
  20.                 <param-value>https://www.colorcc.com:8443/cas</param-value>  
  21.           </init-param>  
  22.           <init-param>  
  23.                 <param-name>serverName</param-name>  
  24.                 <param-value>http://localhost:8080</param-value>  
  25.           </init-param>  
  26.     <!--   <init-param>  
  27.                 <param-name>redirectAfterValidation</param-name>  
  28.                 <param-value>false</param-value>  
  29.           </init-param> -->  
  30.     </filter>  
  31.   
  32.     <filter-mapping>  
  33.         <filter-name>CAS Authentication Filter</filter-name>  
  34.         <url-pattern>/*</url-pattern>  
  35.     </filter-mapping>  
  36.     <filter-mapping>  
  37.         <filter-name>CAS Validation Filter</filter-name>  
  38.         <url-pattern>/*</url-pattern>  
  39.     </filter-mapping>  
  40. ...  
...

<filter>
		  <filter-name>CAS Authentication Filter</filter-name>
		  <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
		  <init-param>
			    <param-name>casServerLoginUrl</param-name>
			    <param-value>https://www.colorcc.com:8443/cas/login</param-value>
		  </init-param>
		  <init-param>
			    <param-name>serverName</param-name>
			    <param-value>http://localhost:8080</param-value>
		  </init-param>
	</filter>
	<filter>
		  <filter-name>CAS Validation Filter</filter-name>
		  <filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
		  <init-param>
			    <param-name>casServerUrlPrefix</param-name>
			    <param-value>https://www.colorcc.com:8443/cas</param-value>
		  </init-param>
		  <init-param>
			    <param-name>serverName</param-name>
			    <param-value>http://localhost:8080</param-value>
		  </init-param>
 	<!--	  <init-param>
			    <param-name>redirectAfterValidation</param-name>
			    <param-value>false</param-value>
		  </init-param> -->
	</filter>

	<filter-mapping>
		<filter-name>CAS Authentication Filter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<filter-mapping>
		<filter-name>CAS Validation Filter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
...

 

2.  AuthenticationFilter 代码:

Java代码 复制代码 收藏代码
  1. public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {   
  2.         final HttpServletRequest request = (HttpServletRequest) servletRequest;   
  3.         final HttpServletResponse response = (HttpServletResponse) servletResponse;   
  4.         final HttpSession session = request.getSession(false);   
  5.         final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;   
  6.         // 如果 session 中有 assertion,则结束 authentication 过滤器,直接跳到下一个过滤器   
  7.         if (assertion != null) {   
  8.             filterChain.doFilter(request, response);   
  9.             return;   
  10.         }   
  11.   
  12.         //  2.1 如果 session 中无 assertion, 则构造 service,  如 http://www.web.com/a1   
  13.        <STRONG> final String serviceUrl = constructServiceUrl(request, response);</STRONG>   
  14.   
  15.   
  16.   
  17.   
  18.   
  19.         final String ticket = CommonUtils.safeGetParameter(request,getArtifactParameterName());   
  20.         final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);   
  21.   
  22.         // 如果 request 中有 ticke变量,则结束本过滤器,直接跳到下一个过滤器   
  23.         if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {   
  24.             filterChain.doFilter(request, response);   
  25.             return;   
  26.         }   
  27.   
  28.         final String modifiedServiceUrl;   
  29.   
  30.         log.debug("no ticket and no assertion found");   
  31.         if (this.gateway) {   
  32.             log.debug("setting gateway attribute in session");   
  33.             modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);   
  34.         } else {   
  35.             modifiedServiceUrl = serviceUrl;   
  36.   
  37.         }   
  38.   
  39.         if (log.isDebugEnabled()) {   
  40.             log.debug("Constructed service url: " + modifiedServiceUrl);   
  41.         }   
  42.   
  43.         // 2.2 否则构造重定向 URL, 其中 casServerLoginUrl 为 web.xml 中 filter 配置,eg: https://www.cas-server.com/cas/login?service=http://www.web.com/a1   
  44.        final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);   
  45.   
  46.   
  47.         if (log.isDebugEnabled()) {   
  48.             log.debug("redirecting to \"" + urlToRedirectTo + "\"");   
  49.         }   
  50.   
  51.         //  2.3 重定向到 CAS server    
  52.         response.sendRedirect(urlToRedirectTo);<EM>   
  53. </EM>   
  54.   
  55.   
  56.   
  57.   
  58.   
  59.     }  
public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
        final HttpServletRequest request = (HttpServletRequest) servletRequest;
        final HttpServletResponse response = (HttpServletResponse) servletResponse;
        final HttpSession session = request.getSession(false);
        final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
        // 如果 session 中有 assertion,则结束 authentication 过滤器,直接跳到下一个过滤器
        if (assertion != null) {
            filterChain.doFilter(request, response);
            return;
        }

        //  2.1 如果 session 中无 assertion, 则构造 service,  如 http://www.web.com/a1
        final String serviceUrl = constructServiceUrl(request, response);





        final String ticket = CommonUtils.safeGetParameter(request,getArtifactParameterName());
        final boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);

        // 如果 request 中有 ticke变量,则结束本过滤器,直接跳到下一个过滤器
        if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {
            filterChain.doFilter(request, response);
            return;
        }

        final String modifiedServiceUrl;

        log.debug("no ticket and no assertion found");
        if (this.gateway) {
            log.debug("setting gateway attribute in session");
            modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
        } else {
            modifiedServiceUrl = serviceUrl;

        }

        if (log.isDebugEnabled()) {
            log.debug("Constructed service url: " + modifiedServiceUrl);
        }

        // 2.2 否则构造重定向 URL, 其中 casServerLoginUrl 为 web.xml 中 filter 配置,eg: https://www.cas-server.com/cas/login?service=http://www.web.com/a1
       final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);


        if (log.isDebugEnabled()) {
            log.debug("redirecting to \"" + urlToRedirectTo + "\"");
        }

        //  2.3 重定向到 CAS server 
        response.sendRedirect(urlToRedirectTo);





    }

  2.1 构造 service url:    http://www.web.com/a1

Java代码 复制代码 收藏代码
  1. protected final String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response) {   
  2.         return CommonUtils.constructServiceUrl(request, response, this.service, this.serverName, this.artifactParameterName, this.encodeServiceUrl);   
  3.     }  
protected final String constructServiceUrl(final HttpServletRequest request, final HttpServletResponse response) {
        return CommonUtils.constructServiceUrl(request, response, this.service, this.serverName, this.artifactParameterName, this.encodeServiceUrl);
    }

 

3. 重定向URL:  https://www.cas-server.com/cas/login?service=http://www.web.com/a1, 其中 cas server的 web.xml:

Java代码 复制代码 收藏代码
  1. <servlet>   
  2.     <servlet-name>cas</servlet-name>   
  3.     <servlet-class>   
  4.       org.jasig.cas.web.init.SafeDispatcherServlet   
  5.     </servlet-class>   
  6.     <init-param>   
  7.       <param-name>publishContext</param-name>   
  8.       <param-value>false</param-value>   
  9.     </init-param>   
  10.     <load-on-startup>1</load-on-startup>   
  11.   </servlet>   
  12.        
  13.   <servlet-mapping>   
  14.     <servlet-name>cas</servlet-name>   
  15.     <url-pattern>/login</url-pattern>   
  16.   </servlet-mapping>  
<servlet>
    <servlet-name>cas</servlet-name>
    <servlet-class>
      org.jasig.cas.web.init.SafeDispatcherServlet
    </servlet-class>
    <init-param>
      <param-name>publishContext</param-name>
      <param-value>false</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
	
  <servlet-mapping>
    <servlet-name>cas</servlet-name>
    <url-pattern>/login</url-pattern>
  </servlet-mapping>

 

     3.1  SafeDispatcherServlet 使用 Spring DispatcherServlet 作为 delegate

 

Java代码 复制代码 收藏代码
  1. public final class SafeDispatcherServlet extends HttpServlet {   
  2.   
  3.     // 定义 Spring DispatcherServlet 作为 delegate   
  4.     private DispatcherServlet delegate = new DispatcherServlet();   
  5.   
  6.     // 使用 delegate 初始化 servlet    
  7.     public void init(final ServletConfig config) {   
  8.         try {   
  9.             this.delegate.init(config);   
  10.   
  11.         } catch (final Throwable t) {   
  12.          ...   
  13.   
  14.      // 使用 delegate 的 service 执行 web 操作   
  15.      public void service(final ServletRequest req, final ServletResponse resp)   
  16.         throws ServletException, IOException {   
  17.         if (this.initSuccess) {   
  18.             this.delegate.service(req, resp);   
  19.         } else {   
  20.             throw new ApplicationContextException(   
  21.                 "Unable to initialize application context.");   
  22.         }   
  23.     }  
public final class SafeDispatcherServlet extends HttpServlet {

    // 定义 Spring DispatcherServlet 作为 delegate
    private DispatcherServlet delegate = new DispatcherServlet();

    // 使用 delegate 初始化 servlet 
    public void init(final ServletConfig config) {
        try {
            this.delegate.init(config);

        } catch (final Throwable t) {
         ...

     // 使用 delegate 的 service 执行 web 操作
     public void service(final ServletRequest req, final ServletResponse resp)
        throws ServletException, IOException {
        if (this.initSuccess) {
            this.delegate.service(req, resp);
        } else {
            throw new ApplicationContextException(
                "Unable to initialize application context.");
        }
    }
 

    3.2 cas-servlet.xml 配置文件如下, 可以看到 login 对应的 webflow 为: login-webflow.xml

 

Java代码 复制代码 收藏代码
  1. <webflow:flow-registry id="flowRegistry" flow-builder-services="builder">   
  2.   <webflow:flow-location path="/WEB-INF/login-webflow.xml" id="login"/>   
  3. </webflow:flow-registry>  
  <webflow:flow-registry id="flowRegistry" flow-builder-services="builder">
    <webflow:flow-location path="/WEB-INF/login-webflow.xml" id="login"/>
  </webflow:flow-registry>

    3.3  根据 login-webflow.xml 配置文件(结合 cas-servlet.xml):

 

Java代码 复制代码 收藏代码
  1. <on-start>   
  2.         <evaluate expression="initialFlowSetupAction" />   
  3.     </on-start>   
  4.   
  5. <bean id="initialFlowSetupAction" class="org.jasig.cas.web.flow.InitialFlowSetupAction"  
  6.         p:argumentExtractors-ref="argumentExtractors"  
  7.         p:warnCookieGenerator-ref="warnCookieGenerator"  
  8.         p:ticketGrantingTicketCookieGenerator-ref="ticketGrantingTicketCookieGenerator"/>  
<on-start>
        <evaluate expression="initialFlowSetupAction" />
    </on-start>

<bean id="initialFlowSetupAction" class="org.jasig.cas.web.flow.InitialFlowSetupAction"
        p:argumentExtractors-ref="argumentExtractors"
        p:warnCookieGenerator-ref="warnCookieGenerator"
        p:ticketGrantingTicketCookieGenerator-ref="ticketGrantingTicketCookieGenerator"/>

     3.4 InitialFlowSetupAction

 

Java代码 复制代码 收藏代码
  1. protected Event doExecute(final RequestContext context) throws Exception {   
  2.         final HttpServletRequest request = WebUtils.getHttpServletRequest(context);   
  3.         if (!this.pathPopulated) {   
  4.             final String contextPath = context.getExternalContext().getContextPath();   
  5.             final String cookiePath = StringUtils.hasText(contextPath) ? contextPath + "/" : "/";   
  6.             logger.info("Setting path for cookies to: "  
  7.                 + cookiePath);   
  8.             this.warnCookieGenerator.setCookiePath(cookiePath);   
  9.             this.ticketGrantingTicketCookieGenerator.setCookiePath(cookiePath);   
  10.             this.pathPopulated = true;   
  11.         }   
  12.            
  13.         // 给 FlowScope 的设置 ticketGrantingTicketId, warnCookieValue 参数   
  14.         context.getFlowScope().put(   
  15.             "ticketGrantingTicketId"this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request));   
  16.         context.getFlowScope().put("warnCookieValue",   
  17.             Boolean.valueOf(this.warnCookieGenerator.retrieveCookieValue(request)));   
  18.           
  19.          // 3.4.1 抽取 service 参数   
  20.         final Service service = WebUtils.getService(this.argumentExtractors, context);   
  21.   
  22.         if (service != null && logger.isDebugEnabled()) {   
  23.             logger.debug("Placing service in FlowScope: " + service.getId());   
  24.         }   
  25.   
  26.         // 给 FlowScope 的设置 service 参数   
  27.         context.getFlowScope().put("service", service);   
  28.   
  29.         return result("success");   
  30.     }  
protected Event doExecute(final RequestContext context) throws Exception {
        final HttpServletRequest request = WebUtils.getHttpServletRequest(context);
        if (!this.pathPopulated) {
            final String contextPath = context.getExternalContext().getContextPath();
            final String cookiePath = StringUtils.hasText(contextPath) ? contextPath + "/" : "/";
            logger.info("Setting path for cookies to: "
                + cookiePath);
            this.warnCookieGenerator.setCookiePath(cookiePath);
            this.ticketGrantingTicketCookieGenerator.setCookiePath(cookiePath);
            this.pathPopulated = true;
        }
        
        // 给 FlowScope 的设置 ticketGrantingTicketId, warnCookieValue 参数
        context.getFlowScope().put(
            "ticketGrantingTicketId", this.ticketGrantingTicketCookieGenerator.retrieveCookieValue(request));
        context.getFlowScope().put("warnCookieValue",
            Boolean.valueOf(this.warnCookieGenerator.retrieveCookieValue(request)));
       
         // 3.4.1 抽取 service 参数
        final Service service = WebUtils.getService(this.argumentExtractors, context);

        if (service != null && logger.isDebugEnabled()) {
            logger.debug("Placing service in FlowScope: " + service.getId());
        }

        // 给 FlowScope 的设置 service 参数
        context.getFlowScope().put("service", service);

        return result("success");
    }

     3.4.1  WebApplicationService.getService

Java代码 复制代码 收藏代码
  1. public static WebApplicationService getService(   
  2.         final List<ArgumentExtractor> argumentExtractors,   
  3.         final HttpServletRequest request) {   
  4.         for (final ArgumentExtractor argumentExtractor : argumentExtractors) {   
  5.                
  6.             // 3.4.1.1 通过配置的 argumentExtractor 抽取 service   
  7.             final WebApplicationService service = argumentExtractor.extractService(request);   
  8.   
  9.             if (service != null) {   
  10.                 return service;   
  11.             }   
  12.         }   
  13.   
  14.         return null;   
  15.     }  
public static WebApplicationService getService(
        final List<ArgumentExtractor> argumentExtractors,
        final HttpServletRequest request) {
        for (final ArgumentExtractor argumentExtractor : argumentExtractors) {
            
            // 3.4.1.1 通过配置的 argumentExtractor 抽取 service
            final WebApplicationService service = argumentExtractor.extractService(request);

            if (service != null) {
                return service;
            }
        }

        return null;
    }

 

     3.4.1.1  CasArgumentExtractor 代码

Java代码 复制代码 收藏代码
  1. public final class CasArgumentExtractor extends AbstractSingleSignOutEnabledArgumentExtractor {   
  2.   
  3.     public final WebApplicationService extractServiceInternal(final HttpServletRequest request) {   
  4.         return SimpleWebApplicationServiceImpl.createServiceFrom(request, getHttpClientIfSingleSignOutEnabled());   
  5.     }   
  6. }   
  7.   
  8. // SimpleWebApplicationServiceImpl   
  9.     private static final String CONST_PARAM_SERVICE = "service";   
  10.     private static final String CONST_PARAM_TARGET_SERVICE = "targetService";   
  11.     private static final String CONST_PARAM_TICKET = "ticket";   
  12.     private static final String CONST_PARAM_METHOD = "method";   
  13.   
  14. public static SimpleWebApplicationServiceImpl createServiceFrom(   
  15.         final HttpServletRequest request, final HttpClient httpClient) {   
  16.         final String targetService = request   
  17.             .getParameter(CONST_PARAM_TARGET_SERVICE);   
  18.         final String method = request.getParameter(CONST_PARAM_METHOD);   
  19.         final String serviceToUse = StringUtils.hasText(targetService)   
  20.             ? targetService : request.getParameter(CONST_PARAM_SERVICE);   
  21.   
  22.         if (!StringUtils.hasText(serviceToUse)) {   
  23.             return null;   
  24.         }   
  25.   
  26.         final String id = cleanupUrl(serviceToUse);   
  27.         final String artifactId = request.getParameter(CONST_PARAM_TICKET);   
  28.   
  29.         return new SimpleWebApplicationServiceImpl(id, serviceToUse,   
  30.             artifactId, "POST".equals(method) ? ResponseType.POST   
  31.                 : ResponseType.REDIRECT, httpClient);   
  32.     }   
  33.   
  34. private SimpleWebApplicationServiceImpl(final String id,   
  35.         final String originalUrl, final String artifactId,   
  36.         final ResponseType responseType, final HttpClient httpClient) {   
  37.         super(id, originalUrl, artifactId, httpClient);   
  38.         this.responseType = responseType;   
  39.     }   
  40.   
  41. protected AbstractWebApplicationService(final String id, final String originalUrl, final String artifactId, final HttpClient httpClient) {   
  42.         this.id = id;   
  43.         this.originalUrl = originalUrl;   
  44.         this.artifactId = artifactId;   
  45.         this.httpClient = httpClient;   
  46.     }  
public final class CasArgumentExtractor extends AbstractSingleSignOutEnabledArgumentExtractor {

    public final WebApplicationService extractServiceInternal(final HttpServletRequest request) {
        return SimpleWebApplicationServiceImpl.createServiceFrom(request, getHttpClientIfSingleSignOutEnabled());
    }
}

// SimpleWebApplicationServiceImpl
    private static final String CONST_PARAM_SERVICE = "service";
    private static final String CONST_PARAM_TARGET_SERVICE = "targetService";
    private static final String CONST_PARAM_TICKET = "ticket";
    private static final String CONST_PARAM_METHOD = "method";

public static SimpleWebApplicationServiceImpl createServiceFrom(
        final HttpServletRequest request, final HttpClient httpClient) {
        final String targetService = request
            .getParameter(CONST_PARAM_TARGET_SERVICE);
        final String method = request.getParameter(CONST_PARAM_METHOD);
        final String serviceToUse = StringUtils.hasText(targetService)
            ? targetService : request.getParameter(CONST_PARAM_SERVICE);

        if (!StringUtils.hasText(serviceToUse)) {
            return null;
        }

        final String id = cleanupUrl(serviceToUse);
        final String artifactId = request.getParameter(CONST_PARAM_TICKET);

        return new SimpleWebApplicationServiceImpl(id, serviceToUse,
            artifactId, "POST".equals(method) ? ResponseType.POST
                : ResponseType.REDIRECT, httpClient);
    }

private SimpleWebApplicationServiceImpl(final String id,
        final String originalUrl, final String artifactId,
        final ResponseType responseType, final HttpClient httpClient) {
        super(id, originalUrl, artifactId, httpClient);
        this.responseType = responseType;
    }

protected AbstractWebApplicationService(final String id, final String originalUrl, final String artifactId, final HttpClient httpClient) {
        this.id = id;
        this.originalUrl = originalUrl;
        this.artifactId = artifactId;
        this.httpClient = httpClient;
    }
 

 

3. Cas20ProxyReceivingTicketValidationFilter 及 AbstractTicketValidationFilter代码:

Java代码 复制代码 收藏代码
  1. public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {   
  2.   
  3.         if (!preFilter(servletRequest, servletResponse, filterChain)) {   
  4.             return;   
  5.         }   
  6.   
  7.         final HttpServletRequest request = (HttpServletRequest) servletRequest;   
  8.         final HttpServletResponse response = (HttpServletResponse) servletResponse;   
  9.         final String ticket = CommonUtils.safeGetParameter(request, getArtifactParameterName());   
  10.   
  11.         // 如果 URL 中包含 ticket 参数,则执行 service 验证工作   
  12.         if (CommonUtils.isNotBlank(ticket)) {   
  13.             if (log.isDebugEnabled()) {   
  14.                 log.debug("Attempting to validate ticket: " + ticket);   
  15.             }   
  16.   
  17.             try {   
  18.                   
  19.                 final Assertion assertion = this.ticketValidator.validate(ticket, constructServiceUrl(request, response));   
  20.   
  21.                 if (log.isDebugEnabled()) {   
  22.                     log.debug("Successfully authenticated user: " + assertion.getPrincipal().getName());   
  23.                 }   
  24.   
  25.                 request.setAttribute(CONST_CAS_ASSERTION, assertion);   
  26.   
  27.                 if (this.useSession) {   
  28.                     request.getSession().setAttribute(CONST_CAS_ASSERTION, assertion);   
  29.                 }   
  30.                 onSuccessfulValidation(request, response, assertion);   
  31.   
  32.                 if (this.redirectAfterValidation) {   
  33.                     log. debug("Redirecting after successful ticket validation.");   
  34.                     response.sendRedirect(constructServiceUrl(request, response));   
  35.                     return;   
  36.                 }   
  37.             } catch (final TicketValidationException e) {   
  38.                 response.setStatus(HttpServletResponse.SC_FORBIDDEN);   
  39.                 log.warn(e, e);   
  40.   
  41.                 onFailedValidation(request, response);   
  42.   
  43.                 if (this.exceptionOnValidationFailure) {   
  44.                     throw new ServletException(e);   
  45.                 }   
  46.   
  47.                 return;   
  48.             }   
  49.         }   
  50.   
  51.         // 如果不包含 ticket, 直接跳过CAS Filter验证,继续其他 filter 或 web app 操作   
  52.         filterChain.doFilter(request, response);   
  53.   
  54.     }  
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics