除了在web.xml添加CAS內(nèi)置的filter外(具體看配置web.xml),我們需要撰寫自己支持CAS集成的客戶化包。大致思路如下:
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
HttpSession session = request.getSession();
//在session中自定義一個(gè)參數(shù),以它來校驗(yàn)是否完成過自動(dòng)登陸
Object user_login = session.getAttribute(AURORA_USER_LOGIN);
if (user_login != null){
//登陸過,就繼續(xù)執(zhí)行其他filter
filterChain.doFilter(request, response);
return;
}
//通過CAS的API獲得登陸賬號(hào)
String loginName = AssertionHolder.getAssertion().getPrincipal().getName();
try {
//執(zhí)行本系統(tǒng)的登陸。跟平常同時(shí)校驗(yàn)用戶名和密碼不同,這里只有用戶名。
executeLoginProc(request,response,loginName);
} catch (Exception e) {
logger.log(Level.SEVERE, "executeLoginProc error:", e);
return;
}
//登陸成功
session.setAttribute(AURORA_USER_LOGIN, Boolean.TRUE);
//跳轉(zhuǎn)到登陸成功后的頁面
response.sendRedirect(roleSelectPageUrl);
}
把這個(gè)class打包成一個(gè)jar拷貝到應(yīng)用的WEB-INF/lib目錄中。
如果有興趣,還可以簡(jiǎn)單了解下org.jasig.cas.client.authentication.AuthenticationFilter這個(gè)CAS內(nèi)置filter的功能
public final void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest)servletRequest;
HttpServletResponse response = (HttpServletResponse)servletResponse;
HttpSession session = request.getSession(false);
//檢查自定義屬性"_const_cas_assertion_"
Assertion assertion = session != null ? (Assertion)session.getAttribute("_const_cas_assertion_") : null;
if (assertion != null) {
//已經(jīng)成功登陸過CAS
filterChain.doFilter(request, response);
return;
}
//拿到url,并檢查url參數(shù)中的ticket是否有效
String serviceUrl = constructServiceUrl(request, response);
String ticket = CommonUtils.safeGetParameter(request, getArtifactParameterName());
boolean wasGatewayed = this.gatewayStorage.hasGatewayedAlready(request, serviceUrl);
if ((CommonUtils.isNotBlank(ticket)) || (wasGatewayed)) {
//ticket有效
filterChain.doFilter(request, response);
return;
}
this.log.debug("no ticket and no assertion found");
String modifiedServiceUrl;
String modifiedServiceUrl;
if (this.gateway) {
this.log.debug("setting gateway attribute in session");
modifiedServiceUrl = this.gatewayStorage.storeGatewayInformation(request, serviceUrl);
} else {
modifiedServiceUrl = serviceUrl;
}
if (this.log.isDebugEnabled()) {
this.log.debug("Constructed service url: " + modifiedServiceUrl);
}
String urlToRedirectTo = CommonUtils.constructRedirectUrl(this.casServerLoginUrl, getServiceParameterName(), modifiedServiceUrl, this.renew, this.gateway);
if (this.log.isDebugEnabled()) {
this.log.debug("redirecting to \"" + urlToRedirectTo + "\"");
}
//重定向到cas的登陸頁面
response.sendRedirect(urlToRedirectTo);
}
在應(yīng)用WEB-INF/web.xml添加filter的內(nèi)容,效果如下所示
<!-- ======================== 單點(diǎn)登錄開始 ======================== -->
<!-- 用于單點(diǎn)退出,該過濾器用于實(shí)現(xiàn)單點(diǎn)登出功能,可選配置-->
<listener>
<listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
</listener>
<!-- 該過濾器用于實(shí)現(xiàn)單點(diǎn)登出功能,可選配置。 -->
<filter>
<filter-name>CAS Single Sign Out Filter</filter-name>
<filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>CAS Single Sign Out Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 該過濾器負(fù)責(zé)用戶的認(rèn)證工作,必須啟用它 -->
<filter>
<filter-name>CASFilter</filter-name>
<filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
<init-param>
<param-name>casServerLoginUrl</param-name>
<param-value>https://sso.:8080/cas/login</param-value>
<!--這里的server是服務(wù)端的IP-->
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>https://sso.:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CASFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- 該過濾器負(fù)責(zé)對(duì)Ticket的校驗(yàn)工作,必須啟用它 -->
<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://sso.:8080/cas</param-value>
</init-param>
<init-param>
<param-name>serverName</param-name>
<param-value>https://sso.:8080</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CAS Validation Filter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!--
該過濾器負(fù)責(zé)實(shí)現(xiàn)HttpServletRequest請(qǐng)求的包裹,
比如允許開發(fā)者通過HttpServletRequest的getRemoteUser()方法獲得SSO登錄用戶的登錄名,可選配置。
-->
<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>
<!--
該過濾器使得開發(fā)者可以通過org.jasig.cas.client.util.AssertionHolder來獲取用戶的登錄名。
比如AssertionHolder.getAssertion().getPrincipal().getName()。
-->
<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>
<!-- 自動(dòng)根據(jù)單點(diǎn)登錄的結(jié)果設(shè)置本系統(tǒng)的用戶信息-->
<filter>
<display-name>AutoSetUserAdapterFilter</display-name>
<filter-name>AutoSetUserAdapterFilter</filter-name>
<filter-class>aurora.plugin.sso.cas.AutoSetUserFilter</filter-class>
<init-param>
<param-name>roleSelectPageUrl</param-name>
<param-value>https://sso.:8080/yourapp/role_select.screen</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>AutoSetUserAdapterFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<!-- ======================== 單點(diǎn)登錄結(jié)束 ======================== -->
前面幾個(gè)都是CAS的標(biāo)準(zhǔn)配置,最后一個(gè)AutoSetUserAdapterFilter(自定義,可以取其他任意名字)才是我們支持cas的客戶化程序。其中roleSelectPageUrl是指用戶完成單點(diǎn)登錄后跳轉(zhuǎn)的頁面。
本文檔撰寫時(shí)java web項(xiàng)目和CAS用同一個(gè)tomcat,所以都用的https。否則只需要配置CAS的鏈接為HTTPS,本項(xiàng)目連接用HTTP。