CAS 統(tǒng)一認(rèn)證集成
1. 前言
在前面的小節(jié)中,我們介紹了兩種統(tǒng)一身份授權(quán)規(guī)范 OAuth2.0 和 SAML2.0,本節(jié)我們介紹另一種統(tǒng)一認(rèn)證解決方案:「CAS」服務(wù)。
CAS 是由 JA-SIG 提供的企業(yè)級(jí)單點(diǎn)認(rèn)證解決方案,推出以來在企業(yè) SSO 場(chǎng)景中被廣泛使用。Spring Security 完整的支持了 CAS,為多應(yīng)用單點(diǎn)認(rèn)證提供了快速集成方案。
更多關(guān)于 CAS 的介紹可以從此獲得:JA-SIG/CAS。
2. CAS 工作原理
CAS 是一套開源的企業(yè)級(jí) SSO 項(xiàng)目,是 B / S 服務(wù)架構(gòu),支持多種通訊協(xié)議。CAS 的主要成員有 CAS 服務(wù)端和 CAS 客戶端。
2.1 CAS 服務(wù)端
CAS 服務(wù)端是一套基于 Spring 框架構(gòu)建的應(yīng)用系統(tǒng),是實(shí)現(xiàn) SSO 的核心構(gòu)成。其軟件層面可分為三個(gè)層次:
- Web 服務(wù)(Spring MVC、Spring Webflow)
- 票據(jù)
- 認(rèn)證系統(tǒng)
2.2 CAS 客戶端
CAS 客戶端是指可以和 CAS 服務(wù)端進(jìn)行安全通訊的業(yè)務(wù)系統(tǒng)。CAS 通訊支持以下協(xié)議:
- CAS(版本1,2,3)
- SAML 1.1
- OpenID
- OAuth(1.0,2.0)
3. Spring Security 集成 CAS
3.1 交互流程
在Spring Security 集成 CAS 認(rèn)證的過程中,共有三個(gè)核心組成部分:瀏覽器、CAS 認(rèn)證中心和基于 Spring Security 構(gòu)建的資源服務(wù)。
瀏覽器、認(rèn)證中心、資源服務(wù)之間的交互流程如下:
- 當(dāng)用戶訪問開放資源時(shí),無需經(jīng)過 CAS 認(rèn)證中心或者資源服務(wù)器上的安全過濾器;
- 當(dāng)用戶訪問私密資源時(shí),資源服務(wù)器
ExceptionTranslationFilter
將會(huì)接收到AccessDeniedException
或是AuthenticationException
,要求用戶進(jìn)行認(rèn)證;
- 資源服務(wù)器在過濾器
ExceptionTranslationFilter
中查找 CAS 認(rèn)證相關(guān)配置CasAuthenticationEntryPoint
,如有則認(rèn)定使用了 CAS 認(rèn)證; - 資源服務(wù)器通過讀取配置
CasAuthenticationEntryPoint
, 將用戶瀏覽器地址跳轉(zhuǎn)到認(rèn)證中心,并指定返回地址; - 認(rèn)證中心查看 Cookies 中是否保存了用戶信息,如有直接認(rèn)證,如果沒有,要求用戶填入其用戶名密碼;
- 認(rèn)證中心判斷登錄是否成功,瀏覽器將跳回原服務(wù)地址,并攜帶票據(jù)參數(shù);
- 回到資源服務(wù)后,
CasAuthenticationFilter
會(huì)持續(xù)監(jiān)聽/login/cas
地址的請(qǐng)求,過濾器會(huì)生成UsernamePasswordAuthenticationToken
用來保存票據(jù)信息,并將認(rèn)證狀態(tài)置為已通過; - 資源服務(wù)的認(rèn)證管理器
AuthenticationManager
傳遞票據(jù)到認(rèn)證中心驗(yàn)證用戶登錄信息; - 認(rèn)證中心認(rèn)證完成后,應(yīng)用服務(wù)會(huì)檢查 CAS 返回的 XML 內(nèi)容,判斷是允許訪問、拒絕訪問或者是其他策略;
- 通過之后,資源服務(wù)的認(rèn)證管理器會(huì)繼續(xù)獲取用戶的權(quán)限信息;
- 如果獲取成功,認(rèn)證中心將生成認(rèn)證憑證 Token 并保存到安全上下文;
- 用戶瀏覽器回到最初訪問地址,并且順利獲得資源。
3.2 配置 CAS 客戶端
從前面的流程中我們看到,與 CAS 認(rèn)證中心集成過程中,Spring Security 用來構(gòu)建資源服務(wù),也就是 CAS 的認(rèn)證客戶端。此處我們來看如何通過 Spring Security 配置 CAS 認(rèn)證客戶端。
3.2.1 服務(wù)票據(jù)認(rèn)證
集成的第一步是配置資源服務(wù)獲取到 Token 之后,如何到 CAS 認(rèn)證中心去驗(yàn)證。多數(shù)情況下,這一步是必須的。我們需要在 Spring 上下文中創(chuàng)建 ServiceProperties
Bean 對(duì)象。
該對(duì)象必須配置 service 屬性,其值為一個(gè) URL 地址,用來被過濾器 CasAuthenticationFilter
偵聽。配置代碼如下:
<bean id="serviceProperties"
class="org.springframework.security.cas.ServiceProperties">
<property name="service"
value="https://localhost:8443/cas-sample/login/cas"/>
<property name="sendRenew" value="false"/>
</bean>
接下來配置 CAS 認(rèn)證相關(guān)過濾器信息,這些配置基本固定。
<security:http entry-point-ref="casEntryPoint">
...
<security:custom-filter position="CAS_FILTER" ref="casFilter" />
</security:http>
<bean id="casFilter"
class="org.springframework.security.cas.web.CasAuthenticationFilter">
<property name="authenticationManager" ref="authenticationManager"/>
</bean>
<bean id="casEntryPoint"
class="org.springframework.security.cas.web.CasAuthenticationEntryPoint">
<property name="loginUrl" value="https://localhost:9443/cas/login"/>
<property name="serviceProperties" ref="serviceProperties"/>
</bean>
完成這步后,我們繼續(xù)配置 CAS 認(rèn)證管理器,添加測(cè)試用的用戶信息。
<security:authentication-manager alias="authenticationManager">
<security:authentication-provider ref="casAuthenticationProvider" />
</security:authentication-manager>
<bean id="casAuthenticationProvider"
class="org.springframework.security.cas.authentication.CasAuthenticationProvider">
<property name="authenticationUserDetailsService">
<bean class="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">
<constructor-arg ref="userService" />
</bean>
</property>
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0" value="https://localhost:9443/cas" />
</bean>
</property>
<property name="key" value="an_id_for_this_auth_provider_only"/>
</bean>
<security:user-service id="userService">
<security:user name="joe" password="{noop}joe" authorities="ROLE_USER" />
</security:user-service>
注意,CAS 體系下的認(rèn)證是交由 CAS 認(rèn)證中心完成的,這一步中配置的密碼并不會(huì)用于認(rèn)證,此處的配置是為了決定認(rèn)證后該用戶所具有的權(quán)限。
至此,CAS 認(rèn)證客戶端的配置完成。
3.2.2 單點(diǎn)注銷
CAS 認(rèn)證協(xié)議中,包含了明確的單點(diǎn)注銷流程,我們可以便捷的集成到我們的認(rèn)證客戶端之中,配置信息如下:
<security:http entry-point-ref="casEntryPoint">
...
<security:logout logout-success-url="/cas-logout.jsp"/>
<security:custom-filter ref="requestSingleLogoutFilter" before="LOGOUT_FILTER"/>
<security:custom-filter ref="singleLogoutFilter" before="CAS_FILTER"/>
</security:http>
<!-- 該過濾器用于接收來自 CAS 認(rèn)證中心的登出請(qǐng)求。(由其他應(yīng)用發(fā)起登出) -->
<bean id="singleLogoutFilter" class="org.jasig.cas.client.session.SingleSignOutFilter"/>
<!-- 該過濾器用于向 CAS 認(rèn)證中心發(fā)送登出請(qǐng)求。(由本應(yīng)用發(fā)起登出) -->
<bean id="requestSingleLogoutFilter"
class="org.springframework.security.web.authentication.logout.LogoutFilter">
<constructor-arg value="https://localhost:9443/cas/logout"/>
<constructor-arg>
<bean class=
"org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler"/>
</constructor-arg>
<property name="filterProcessesUrl" value="/logout/cas"/>
</bean>
登出操作由某一 CAS 客戶端發(fā)起,CAS 認(rèn)證中心接收到之后,會(huì)向所有該用戶已登錄應(yīng)用發(fā)起登出通知,最后實(shí)現(xiàn)全部應(yīng)用的登出效果。
4. 小結(jié)
本節(jié)介紹了 CAS 認(rèn)證體系的工作流程,Spring Security 可方便的實(shí)現(xiàn) CAS 認(rèn)證客戶端功能,CAS 認(rèn)證體系下支持單點(diǎn)登出操作,需要每一個(gè)加入體系的應(yīng)用配置用于處理單點(diǎn)登出的過濾器。
下節(jié)我們將介紹 Java 早期的安全框架 JAAS,已經(jīng)如何用 Spring Security 集成 JAAS 認(rèn)證。