https://github.com/Jasig/java-cas-client
1 客户端配置,我的版本是3.4.1
<!-- CAS Server 通知 CAS Client,删除session,注销登录信息 -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
<init-param>
<param-name>casServerUrlPrefix</param-name>
<param-value>http://192.168.20.103:8080/cas-server-webapp</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<filter>
<filter-name>Encoding</filter-name>
<filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
<init-param>
<param-name>encoding</param-name>
<param-value>UTF-8</param-value>
</init-param>
<init-param>
<param-name>forceEncoding</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>Encoding</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 登录认证,未登录用户导向CAS Server进行认证 -->
<filter>
<filter-name>CAS Filter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>http://192.168.20.103:8080/cas-server-webapp/login</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://192.168.20.103:8080/zgr-cas-integrate</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- CAS Client向CAS Server进行ticket验证 -->
<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>http://192.168.20.103:8080/cas-server-webapp</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>http://192.168.20.103:8080/zgr-cas-integrate</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 封装request, 支持getUserPrincipal等方法-->
<filter>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 存放Assertion到ThreadLocal中 -->
<filter>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Assertion Thread Local Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
2 org.jasig.cas.client.authentication.AuthenticationFilter
检查访问的用户是否需要认证。
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;
if (isRequestUrlExcluded(request)) {
logger.debug("Request is ignored.");
filterChain.doFilter(request, response);
return;
}
final HttpSession session = request.getSession(false);
// 2.1此assertion是在请求经过Cas20ProxyReceivingTicketValidationFilter时被设置,下面会讲到
final Assertion assertion = session != null ? (Assertion) session.getAttribute(CONST_CAS_ASSERTION) : null;
if (assertion != null) { // 2.2如果assertion存在,则直接访问资源
filterChain.doFilter(request, response);
return;
}
final String serviceUrl = constructServiceUrl(request, response); //请求url地址
final String ticket = retrieveTicketFromRequest(request); // 2.3请求里是否携带ticket,主要检查service ticket(ST)
final boolean wasGatewayed = this.gateway && this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
if (CommonUtils.isNotBlank(ticket) || wasGatewayed) {
// 2.4如果ST非空,则访问继续(会被下一个filter-Cas20ProxyReceivingTicketValidationFilter特殊处理)
filterChain.doFilter(request, response);
return;
}
final String modifiedServiceUrl;
logger.debug("no ticket and no assertion found");
if (this.gateway) {
logger.debug("setting gateway attribute in session");
modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
} else {
modifiedServiceUrl = serviceUrl;
}
logger.debug("Constructed service url: {}", modifiedServiceUrl);
final String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl,
getProtocol().getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
logger.debug("redirecting to \"{}\"", urlToRedirectTo);
this.authenticationRedirectStrategy.redirect(request, response, urlToRedirectTo); // 2.5用户未经认证,重定向到cas-server登录页面
}
3.org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter向cas-server验证用户传递的service ticket是否合法
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 String ticket = retrieveTicketFromRequest(request);
if (CommonUtils.isNotBlank(ticket)) { //3.1 只处理ST非空的情况,与前面2.3一致
logger.debug("Attempting to validate ticket: {}", ticket);
try {
final Assertion assertion = this.ticketValidator.validate(ticket,
constructServiceUrl(request, response)); //往cas-server发送请求http://192.168.20.103:8080/cas-server-webapp/serviceValidate?ticket=ST-44-G2dJRpP2dYQnIB14Ydwh-cas01.example.org&service=http%3A%2F%2F192.168.20.103%3A8080%2Fzgr-cas-integrate2%2Fresource%2Fsimple,验证ST的合法性
logger.debug("Successfully authenticated user: {}", assertion.getPrincipal().getName());
request.setAttribute(CONST_CAS_ASSERTION, assertion);
if (this.useSession) { request.getSession().setAttribute(CONST_CAS_ASSERTION, assertion);//ST验证成功后,把assertion放入session,与前面2.1对应
}
onSuccessfulValidation(request, response, assertion);
if (this.redirectAfterValidation) {
logger.debug("Redirecting after successful ticket validation.");
response.sendRedirect(constructServiceUrl(request, response));
return;
}
} catch (final TicketValidationException e) {
//如果验证失败,则抛出异常。失败的原因一般是ST超时而失效
logger.debug(e.getMessage(), e);
onFailedValidation(request, response);
if (this.exceptionOnValidationFailure) {
throw new ServletException(e);
}
response.sendError(HttpServletResponse.SC_FORBIDDEN, e.getMessage());
return;
}
}
filterChain.doFilter(request, response);
}