前端時間學習了,cas 的sso 框架,在這里簡略記錄一下,拉下訪客。而且這兩天又在修改樣式,既郁悶又痛苦,趁這個換換腦子。本篇博客記載的大多都是從網上收集加上自己總結的,並不權威。轉載請注明出處。
首先是下載cas相關的資源,需要的是 cas-server-3.5.2-release.zip 里面包含 cas-server-webapp-3.5.2.war,cas-client-3.2.1-release.zip 里面包含 cas-client-core-3.2.1.jar,另在找一個jar包(casClientNew.jar),版本請隨意,我用的是這兩個版本,未測試其他版本。環境 jdk1.6,tomcat 6.0。
介紹我實現的功能,sso單點登錄,未使用ssl,需特別說明的是,cas的安全保證很大部分依靠ssl,因此,有條件請實現。cas sso 實現的是用戶驗證,用戶進到某個子系統的權限依然由子系統控制(我是寫了一個過濾器實現的)。
接下來開始介紹步驟,至於cas 原理,網上很多介紹,我不再copy了。http://www.cnblogs.com/yonsin/archive/2009/08/29/1556423.html http://blog.csdn.net/maxgong2005/article/details/557052 請自己參考查閱。
第一步是修改cas server 服務端( cas-server-webapp-3.5.2.war),既然是單點登錄一定需要驗證,需要告知cas server如何驗證,我采用的是cas server自己訪問數據庫我指定的表,驗證用戶名和密碼。密碼的加密方式是我自己實現的。我只用到了用戶表的用戶名和密碼兩個字段。cas-server 支持添加用戶屬性(除用戶名和密碼),支持驗證碼,等諸多功能,有興趣請自己研究實現。
首先,配置數據源,找到WEB-INF下的deployerConfigContext.xml文件,deployerConfigContext.xml是 cas-server的重要配置文件,在里面配置數據源,請配置在第一位:
<bean id="casDataSource" class="org.logicalcobwebs.proxool.ProxoolDataSource"> <!--SQL SERVER --> <property name="driver" value="自己選擇驅動類"></property> <property name="driverUrl" value="數據庫字符串"></property> <property name="user" value="用戶名" /> <property name="password" value="密碼" /> <property name="houseKeepingSleepTime" value="相關屬性自己設置" /> <property name="prototypeCount" value="相關屬性自己設置" /> <property name="maximumConnectionCount" value="相關屬性自己設置" /> <property name="minimumConnectionCount" value="相關屬性自己設置" /> <property name="trace" value="true" /> <property name="verbose" value="true" /> </bean>
然后配置自己實現的加密方式,當然你的加密類需要實現他的接口 org.jasig.cas.authentication.handler.PasswordEncoder:
<bean id="passwordEncoder" class="加密方式自己實現" autowire="byName"> </bean>
接下來,找到bean 為 authenticationManager 里面的一個屬性 authenticationHandlers,里面list中的一個bean 類指向 HttpBasedServiceCredentialsAuthenticationHandler 中的一個屬性:p:requireSecure="false" 設置成false 表示 客戶端不啟用 ssl。然后是HttpBasedServiceCredentialsAuthenticationHandler的下面有一個 cas 的jdbc實現bean , SearchModeSearchDatabaseAuthenticationHandler 里面添加你的數據源設置和加密方式設置。
<bean class="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler" abstract="false" lazy-init="default" autowire="default"><!-- dependency-check="default" --> <property name="dataSource" ref="casDataSource" /> <property name="tableUsers" value="用戶表" /> <property name="fieldUser" value="用戶名" /> <property name="fieldPassword" value="密碼" /> <property name="passwordEncoder" ref="passwordEncoder" /> </bean>
在到WEB-INF下的spring-configuration目錄下找到文件ticketGrantingTicketCookieGenerator.xml 設置屬性 p:cookieSecure="false" false表示不啟用ssl。
<bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator" p:cookieSecure="false" p:cookieMaxAge="-1" p:cookieName="CASTGC" p:cookiePath="/cas" />
至此服務端設置完畢,當然還有很多屬性沒有說,有興趣請自己研究。
接下來是客戶端的修改:首先添加相應jia包到客戶端:cas-client-core-3.2.1.jar,casClientNew.jar,然后是配置過濾器,因為我的系統配置的還有webserverice等,所以cas filter的過濾路徑我並沒有配置/*
<!-- cas sso 驗證相關 開始 --> <!--用於單點退出配置 --> <listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class> </listener> <filter> <filter-name>CAS Single Sign Out Filter</filter-name> <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class> </filter> <!--用於單點登錄配置 --> <filter> <filter-name>CAS Filter</filter-name> <filter-class>edu.yale.its.tp.cas.client.filter.CASFilter</filter-class> <!--下面兩個為驗證地址,即cas server端的登錄地址和驗證地址 --> <init-param> <param-name>edu.yale.its.tp.cas.client.filter.loginUrl</param-name> <param-value>http://localhost:8088/cas/login</param-value> </init-param> <init-param> <param-name>edu.yale.its.tp.cas.client.filter.validateUrl</param-name> <param-value>http://localhost:8088/cas/serviceValidate</param-value> </init-param> <!--本工程的URL被攔截的需要驗證的訪問地址 --> <init-param> <param-name>edu.yale.its.tp.cas.client.filter.serverName</param-name> <param-value>localhost:8080</param-value> </init-param> </filter> <!--單點退出的過濾映射路徑--> <filter-mapping> <filter-name>CAS Single Sign Out Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 系統本身登錄 --> <!--<filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping>--> <filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>*.action</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>*.jsp</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>*.html</url-pattern> </filter-mapping> <filter-mapping> <filter-name>CAS Filter</filter-name> <url-pattern>*.js</url-pattern> </filter-mapping> <listener> <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class> </listener> <!-- cas sso 驗證相關 結束-->
client獲取用戶名 ,而且我們假定獲取的用戶名是可信任的:
String username = (String) request.getSession().getAttribute(edu.yale.its.tp.cas.client.filter.CASFilter.CAS_FILTER_USER);
OK,現在為止你的系統已經可以實現單點登錄了,上面的這些基本也是可以從網上隨便搜下就能找到的。接下來我講一下自己的定制。
首先是,登錄頁面修改,cas server的頁面設置在 default_views.properties 文件里,請根據需要修改。然后說下系統的sso單點登錄,有時候我們根據客戶要求會集成多種登錄方式,不僅僅是cas sso這個一種,因此需要你重寫 edu.yale.its.tp.cas.client.filter.CASFilter,根據url選擇性過濾。你重寫的filter繼承自CASFilter,不需過濾直接filterChain.doFilter(request, response);需要過濾的就調用super.doFilter(httprequest, response, filterChain);
然后就是關於potal,cas 框架我們一方面是想實現單點登錄,一方面也希望給客戶做個potal,最初我是計划potal放在casserver里面,但登錄的第一次可以獲取到用戶信息,之后一直獲取不到用戶信息因此就放到了client端。cas 框架本身提供了代理模式,但按照網上配置未成功,就先自己寫了一個驗證方式。假如potal放的client端為A,其他為B、C。A從B、C抽取數據,B、C提供好服務類,集成同一接口配置到spring容器中。A使用URLConnection模擬調用B、C的服務時,A提供服務名作為參數傳遞過去,讓B、C從spring容器里面取。一個是建議json傳輸,然后就是中文可能亂碼解決:result = new String(resultJson.getBytes("iso8859-1"),"UTF-8");還有就是 CASFilter過濾時也可能存在亂碼問題,請自己設置過濾器設置編碼。