1. 客戶端 web.xml 片斷: web
Xml代碼
- ...
-
- <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 代碼: cookie
-
- 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
- <strong> final String serviceUrl = constructServiceUrl(request, response);</strong>
-
-
-
-
-
- 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);<em>
- </em>
-
-
-
-
-
- }
3: session
. 重定向URL: https://www.cas-server.com/cas/login?service=http://www.web.com/a1, 其中 cas server的 web.xml: app
Java代碼
- <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 ui
Java代碼
- 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 this
Java代碼
- <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): lua
Java代碼
- <on-start>
- <evaluate ="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 url
Java代碼
- 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 spa
Java代碼
- 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 代碼 debug
Java代碼
- 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代碼
- public final void doFilter(final ServletRequest servletRequest, final ServletResponse servletResponse, final FilterChain filterChain) throws IOException, ServletException {
-
- if (!preFilter(servletRequest, servletResponse, filterChain)) {
- return;
- }
-
- final HttpServletRequest request = (HttpServletRequest) servletRequest;
- final HttpServletResponse response = (HttpServletResponse) servletResponse;
- final String ticket = CommonUtils.safeGetParameter(request, getArtifactParameterName());
-
- // 若是 URL 中包含 ticket 參數,則執行 service 驗證工做
- if (CommonUtils.isNotBlank(ticket)) {
- if (log.isDebugEnabled()) {
- log.debug("Attempting to validate ticket: " + ticket);
- }
-
- try {
-
- final Assertion assertion = this.ticketValidator.validate(ticket, constructServiceUrl(request, response));
-
- if (log.isDebugEnabled()) {
- log.debug("Successfully authenticated user: " + assertion.getPrincipal().getName());
- }
-
- request.setAttribute(CONST_CAS_ASSERTION, assertion);
-
- if (this.useSession) {
- request.getSession().setAttribute(CONST_CAS_ASSERTION, assertion);
- }
- onSuccessfulValidation(request, response, assertion);
-
- if (this.redirectAfterValidation) {
- log. debug("Redirecting after successful ticket validation.");
- response.sendRedirect(constructServiceUrl(request, response));
- return;
- }
- } catch (final TicketValidationException e) {
- response.setStatus(HttpServletResponse.SC_FORBIDDEN);
- log.warn(e, e);
-
- onFailedValidation(request, response);
-
- if (this.exceptionOnValidationFailure) {
- throw new ServletException(e);
- }
-
- return;
- }
- }
-
- // 若是不包含 ticket, 直接跳過CAS Filter驗證,繼續其餘 filter 或 web app 操做
- filterChain.doFilter(request, response);
-
- }