使用 CAS 在 Tomcat 中實現單點登錄

1.  什麼是單點登錄?

單點登錄(Single Sign On , 簡稱 SSO )是目前比較流行的服務於企業業務整合的解決方案之一, SSO 使得在多個應用系統中,用戶只需要登錄一次就可以訪問所有相互信任的應用系統。CAS(Central Authentication Service)是一款不錯的針對 Web 應用的單點登錄框架,本文介紹了 CAS 的原理、協議、在 Tomcat 中的配置和使用,對於採用 CAS 實現輕量級單點登錄解決方案的入門讀者具有一定指導作用。


CAS 是 Yale 大學發起的一個開源項目,旨在爲 Web 應用系統提供一種可靠的單點登錄方法,CAS 在 2004 年 12 月正式成爲 JA-SIG 的一個項目。CAS 具有以下特點:

  • 開源的企業級單點登錄解決方案。
  • CAS Server 爲需要獨立部署的 Web 應用。
  • CAS Client 支持非常多的客戶端(這裏指單點登錄系統中的各個 Web 應用),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。


好頂贊


再推薦一個關於單點登錄配置介紹的博客,

IBM博文,很犀利啊

http://www.ibm.com/developerworks/cn/opensource/os-cn-cas/

 tomcat SSL的配置

http://www.oschina.net/question/12_23148          

 官方文檔 權威啊  裏面有很多demo和優秀的博客,很多博客都是從這裏翻譯來的

https://wiki.jasig.org/display/CASC/Home  

http://hi.baidu.com/mlkoismlhkbmsvq/item/cafb013227c4689bb80c03bb    

http://www.blogjava.net/Jack2007/archive/2008/04/10/191795.html   


本文還參考了 一下博客:

http://www.cnblogs.com/dycg/archive/2013/04/04/2999012.html

http://blog.csdn.net/wqmain/article/details/8562602




2.  測試環境

服務端:Windows XP+ JDK1.7 + Tomcat7

客戶端:Windows XP+ JDK1.7 + Tomcat7

CAS 服務端版本爲 3.5.0,對應客戶端jar包版本爲 3.2.1

CAS 下載地址:http://www.jasig.org/cas/download   這個是官方地址, 我一直進不去,我在CSDN下載的,可以使用


2.  服務器端怎麼安裝?

CAS Server 是一套基於 Java 實現的服務,該服務以一個 Java Web Application 單獨部署在與 servlet2.3 兼容的 Web 服務器上,另外,由於 Client 與 CAS Server 之間的交互採用 Https 協議,因此部署 CAS Server 的服務器還需要支持 SSL 協議

一、     生成服務端密鑰文件

登錄服務器打開一個CMD窗口(開始菜單 -> 運行輸入cmd後回車)並切換到tomcat安裝目錄下(如:c:\tomcat-cas),執行如下命令:

keytool -genkey -alias casserver -keypass demosso -keyalg RSA -keystore casserver.keystore -validity 365


執行後,可以看到tomcat安裝目錄下生成了一個casserver.keystore文件。如下圖:


說明:-alias指定別名爲casserver;-keyalg指定RSA算法;-keypass指定私鑰密碼;-keystore指定密鑰文件名稱爲casserver.keystore;-validity指定有效期爲365天。另外提示的輸入keystore密碼應與-keypass指定的相同;您的名字與姓氏是CAS服務器使用的域名(不能是IP,也不能是localhost),其它項隨意填。

注意:服務器上如果有多個JDK,請確認環境變量中的JDK路徑爲tomcat所使用的JDK,如果不在環境變量中,也可切換到指定JDK的bin目錄下執行命令;提示的輸入keystore密碼應與-keypass必須與指定的相同,否則後面tomcat啓動會報IO異常(Cannot recover key)。


二、     生成服務端證書

根據以上生成的服務端的密鑰文件可以導出服務端證書,執行以下命令:

keytool -export -alias casserver -storepass demosso -file casserver.cer -keystore casserver.keystore


執行後,可以看到tomcat安裝目錄下生成了一個casserver.cer文件。如下圖:


說明:-alias指定別名爲casserver;-storepass指定私鑰爲demosso;-file指定導出證書的文件名爲casserver.cer;-keystore指定之前生成的密鑰文件的文件名。

注意:-alias和-storepass必須爲生成casserver.keystore密鑰文件時所指定的別名和密碼,否則證書導出失敗,報如下錯誤:



三、     導入證書文件到cacerts 密鑰庫文件

導入以上生成的服務端的證書文件到一個cacerts密鑰庫文件,執行以下命令:

keytool -import -trustcacerts -alias casserver-storepass demosso  -file casserver.cer–keystore cacerts


執行後,可以看到tomcat安裝目錄下生成了一個cacerts文件。如下圖:



如果java的安裝目錄有空格,執行這句會報錯,  我的做法是先把jdk中的cacerts拷貝到根目錄下,再執行export操作


四、     服務端Tomcat配置

在製作完成密鑰文件、證書文件、密鑰庫文件後即可進行服務端Tomcat的配置。打開$CATALINA_HOME/conf/server.xml文件,註釋掉如下代碼段:

<Connector port="80"protocol="HTTP/1.1" connectionTimeout="20000" redirectPort="8443"/>

並取消註釋<Connectorport="8443" protocol="HTTP/1.1" SSLEnabled="true"…/>代碼段,修改後如下:


說明:port一般爲8443或443,最常用的是443端口(https默認端口),這樣https方式訪問的時候可以不加端口號(如:https://sso.demo.com/cas/login);keystoreFile爲tomcat目錄下的密鑰文件;keystorePass爲私鑰密碼;truststoreFile爲生成的信任文件,如果此處不指定則默認爲$JAVA_HOME/jre/lib/security/cacerts文件;其它屬性默認即可。


五、     生成客戶端密鑰庫文件

單向認證的客戶端配置只需生成客戶端信任文件caserts即可。首先將服務端生成的證書文件(之前生成的casserver.cer文件)複製到$JAVA_HOME/jre/lib/security下,然後打開CMD窗口切換到$JAVA_HOME/jre/lib/security下並執行命令:

keytool -import -trustcacerts -alias casclient-storepass ssoclient -file casserver.cer -keystore cacerts


執行後,可以看到$JAVA_HOME/jre/lib/security目錄下生成了一個cacerts文件。如下圖:


OK到這裏 SSL協議配置完成了。如果顯示密碼錯誤,請使用 changeit ,這個是jdk默認的證書密碼


二、安裝server端

咱們需要下載 cas-server-3.4.10-release.zip,這個裏面包含war包和lib包

解壓cas-server-3.4.10-release.zip\cas-server-3.4.10\modules\cas-server-webapp-3.4.10.war並改名爲 cas.war,然後放到tomcat webapp目錄下,啓動tomcat

訪問: https://localhost:8443/cas/login



 

用戶名密碼: admin admin

提示單點登錄成功

 

 

上面是最基本的單點登錄,用戶名和密碼是寫死在配置文件中,那麼我們如何使用JDBC呢?


使用JDBC登錄


打開cas\WEB-INF\deployerConfigContext.xml

其中92行的

<bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />

就是簡單的用戶名密碼驗證,在實際中是用不到的。刪掉他。

然後添加JDBC認證,註冊一個dataSource,注意添加的位置,應當添加到bean標籤的同級,不然server端啓動不了

<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">

   <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>

   <property name="url"><value>jdbc:mysql://localhost:3306/cas_demo</value></property>

   <property name="username"><value>root</value></property>

   <property name="password"><value>123456</value></property>

</bean>

在剛剛註釋的bean位置添加jdbc的bean,這裏還包含一個MD5加密

<bean id="MD5PasswordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">

    <constructor-arg index="0">

        <value>MD5</value>

    </constructor-arg>

</bean>

 

<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">

    <property name="dataSource" ref="dataSource"></property>

    <property name="sql" value="select password from user where login_name=?"></property>

    <property name="passwordEncoder" ref="MD5PasswordEncoder"></property>

</bean>

有spring基礎的一般都能看懂。 

然後複製cas-server-3.4.10-release.zip\cas-server-3.4.10\modules下的cas-server-support-jdbc-3.4.10.jar以及mysql數據庫的mysql.jar到cas/WEB-INF/lib目錄下

要注意的是,org.jasig.cas.authentication.handler.DefaultPasswordEncoder加密後的字符串是小寫的32位MD5密鑰。

到此服務端配置完成。


客戶端配置


下載cas-client-XXX-release.zip

然後解壓出cas-client-3.2.1-release.zip\cas-client-3.2.1\modules下的cas-client-core-3.2.1.jar,放入你的web項目lib目錄中

假設我有這麼一個項目:

現在,我要做的就是修改web.xml

<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 Authentication Filter</filter-name>
   <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>
   <init-param>
     <param-name>casServerLoginUrl</param-name>
     <param-value>https://sso.demo.com/cas/login</param-value>
   </init-param>
   <init-param>
     <param-name>renew</param-name>
     <param-value>false</param-value>
   </init-param>
   <init-param>
     <param-name>gateway</param-name>
     <param-value>false</param-value>
   </init-param>
   <init-param>
     <param-name>serverName</param-name>
     <param-value>http://192.68.69.75:80</param-value>
   </init-param>
</filter>
<filter>
<filter-name>CASValidation Filter</filter-name>
<filter-class>org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>
   <init-param>
     <param-name>casServerUrlPrefix</param-name>
     <param-value>https://sso.demo.com/cas</param-value>
   </init-param>
   <init-param>
     <param-name>serverName</param-name>
     <param-value>http://192.68.69.75:80</param-value>
   </init-param>
   <init-param>
     <param-name>useSession</param-name>
     <param-value>true</param-value>
   </init-param>
   <init-param>
     <param-name>redirectAfterValidation</param-name>
     <param-value>true</param-value>
   </init-param>
</filter>
<filter>
   <filter-name>CAS HttpServletRequest WrapperFilter</filter-name>
   <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
 </filter>
 <filter>
   <filter-name>LoginFilter</filter-name>
   <filter-class>demo.filter.LoginFilter</filter-class>
 </filter>
<filter-mapping>
   <filter-name>CAS Single Sign Out Filter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
<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>
<filter-mapping>
   <filter-name>CAS HttpServletRequest WrapperFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
   <filter-name>LoginFilter</filter-name>
   <url-pattern>/*</url-pattern>
</filter-mapping>

說明:LoginFilter內容一般爲獲取用戶基本信息、菜單信息然後保存到session中;sso.demo.com爲CAS服務器的域名,也就是之前使用keytool –genkey命令指定的“名字與姓氏”。若未申請域名,也可以本地模擬實現域名解析,編輯C:\WINDOWS\system32\drivers\etc\hosts文件添加:CAS服務器IP  sso.demo.com 即可),如下圖:


注意:serverName屬性值爲客戶端實際IP地址,可以爲域名但絕不能爲localhost!

1、   客戶端程序單點退出功能,需要訪問https://sso.demo.com/cas/logout,下面提供了一個示例,當點擊退出按鈕(或超鏈接)時,調用javascript方法ssoLogout()。ssoLogout()定義如下(可根據實際需求自行修改):

<scripttype="text/javascript">
function ssoLogout(){
    if(confirm('確定要退出系統嗎?')){
		top.location.href ='https://sso.demo.com/cas/logout?service='+location.protocol+'//'+location.host+location.pathname;
    }
}
</script>

上面講的是CAS單獨部署的情況,也就是與其它應用分開部署。但有些情況是CAS與其它應用部署到同一臺機器同一個Tomcat(關鍵問題是使用同一個JDK),這種情況下,服務端Tomcat配置中的<Connector truststoreFile屬性就要指定爲jdk下的cacerts文件路徑或者直接註釋掉(默認會找$JAVAHOME\jre\lib\security\下的cacerts文件)。這樣服務端和客戶端是同一個,也就不必再根據服務端證書生成客戶端密鑰庫文件了。


常見配置錯誤

1、  CAS服務端Tomcat啓動後報錯:Error initializing endpoint java.io.IOException: Cannot recover key

是由於生成服務端密鑰文件時所指定的keypass與提示輸入的“keystore密碼”不一致。

2、  javax.servlet.ServletException: org.jasig.cas.client.validation.TicketValidationException:紲ㄦ牴'ST-2-hozuLnLtIVGeaD5yju0Y-cas'涓嶇鍚堢洰鏍囨湇鍔?

一般是由於客戶端應用web.xml中配置的serverName屬性值爲localhost或CAS服務端cas-servlet.xml配置文件中的<bean logoutController/>沒加p:followServiceRedirects="true"退出後重定向屬性。

3、  SSLHandshakeException: java.security.cert.CertificateException: Nosubject alternative names present

是由於客戶端應用web.xml配置中的casServerLoginUrl和casServerUrlPrefix兩個URL屬性的域名與證書中定義的不一致。



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章