學習筆記_java CAS單點登錄(SSO)

一. 教程前言
  1. 教程目的:從頭到尾細細道來單點登錄服務器及客戶端應用的每個步驟
  2. 單點登錄SSO):請看百科解釋猛擊這裏打開
  3. 本教程使用的SSO服務器是Yelu大學研發的CAS(Central Authentication Server),
    官網:http://www.jasig.org/cas
  4. 本教程環境:
    • Tomcat6.0.29
    • JDK6
    • CAS Server版本:cas-server-3.4.3.1
    • CAS Client版本:cas-client-3.1.12
    • 教程撰寫日期:2010-11-05
    • 教程作者:咖啡兔

二、創建證書

囉嗦幾句:證書是單點登錄認證系統中很重要的一把鑰匙,客戶端於服務器的交互安全靠的就是證書;本教程由於是演示所以就自己用JDK自帶的keytool工具生成證書;如果以後真正在產品環境中使用肯定要去證書提供商去購買,證書認證一般都是由VeriSign認證,
中文官方網站:http://www.verisign.com/cn/

  1. 用JDK自帶的keytool工具生成證書:

    命令:keytool -genkey -alias wsria -keyalg RSA -keystore d:/keys/wsriakey

無圖不給力,有圖有真相:

用keytool生成證書


具體的輸入項圖片中都有說明,有一點我要解釋一下;在輸入完密碼後提示輸入域名是我輸入的是sso.wsria.com,其實這個域名是不存在的,但是我爲了演示所以虛擬了這個域名,技巧在於修改C:\Windows\System32\drivers\etc\hosts,添加內容如下:

127.0.0.1 sso.wsria.com

這樣在訪問sso.wsria.com的時候其實是訪問的127.0.0.1也就是本機

嚴重提醒:提示輸入域名的時候不能輸入IP地址

三、導出證書

命令:D:\keys>keytool -export -file d:/keys/wsria.crt -alias wsria -keystore d:/keys/wsriakey

來點顏色:

使用keytool導出證書


至此導出證書完成,可以分發給應用的JDK使用了,接下來講解客戶端的JVM怎麼導入證書

四、爲客戶端的JVM導入證書

命令:keytool -import -keystore D:\tools\jdk\1.6\jdk1.6.0_20\jre\lib\security\cacerts -file D:/keys/wsria.crt -alias wsria

來點顏色瞧瞧:

爲客戶端JVM導入證書


特別說明:D:\tools\jdk\1.6\jdk1.6.0_20\jre\lib\security — 是jre的目錄;密碼還是剛剛輸入的密碼。
至此證書的創建、導出、導入到客戶端JVM都已完成,下面開始使用證書到Web服務器中,本教程使用tomcat。

五、應用證書到Web服務器-Tomcat

說是應用起始做的事情就是啓用Web服務器(Tomcat)的SSL,也就是HTTPS加密協議,爲什麼加密我就不用囉嗦了吧……
準備好一個乾淨的tomcat,本教程使用的apache-tomcat-6.0.29
打開tomcat目錄的conf/server.xml文件,開啓83和87行的註釋代碼,並設置keystoreFile、keystorePass修改結果如下:

[html] view plaincopy
  1. <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"  
  2.                maxThreads="150" scheme="https" secure="true"  
  3.                clientAuth="false" sslProtocol="TLS"   
  4.            keystoreFile="D:/keys/wsriakey"  
  5.            keystorePass="wsria.com"  
  6. />  


 

參數說明:

  • keystoreFile:在第一步創建的key存放位置
  • keystorePass:創建證書時的密碼

好了,到此Tomcat的SSL啓用完成,現在你可以啓動tomcat試一下了,例如本教程輸入地址:https://sso.wsria.com:8443/
打開的是:

瀏覽器提示證書錯誤


好的,那麼我們點擊“繼續瀏覽此網站(不推薦)。 ”,現在進入Tomcat目錄了吧,如果是那麼你又向成功邁進了一步。
OK,接下來要配置CAS服務器了。

六、CAS服務器初體驗

  1. CAS服務端下載:http://www.jasig.org/cas/download
  2. 下載完成後將cas-server-3.4.3.1.zip解壓,解壓cas-server-3.4.3/modules/cas-server-webapp-3.4.3.1.war,改名爲cas,然後複製cas目錄到你的tomcat/webapp目錄下
  3. 現在可以訪問CAS應用了,當然要使用HTTPS加密協議訪問,
    例如本教程地址:https://sso.wsria.com:8443/cas/login ,現在打開了CAS服務器的頁面輸入admin/admin點擊登錄(CAS默認的驗證規則只要用戶名和密碼相同就通過)所以如果你看到下面的這張圖片你就成功了

CAS登錄成功


你成功了嗎?如果沒有成功請再檢查以上步驟!

七、CAS服務器深入配置

上面的初體驗僅僅是簡單的身份驗證,實際應用中肯定是要讀取數據庫的數據,下面我們來進一步配置CAS服務器怎麼讀取數據庫的信息進行身份驗證。
首先打開tomcat/webapp/cas/WEB-INF/deployerConfigContext.xml文件,配置的地方如下:

  1. 找到第92行處,註釋掉:SimpleTestUsernamePasswordAuthenticationHandler這個驗證Handler,這個是比較簡單的,只是判斷用戶名和密碼相同即可通過,這個肯定不能在實際應用中使用,棄用!
  2. 註釋掉92行後在下面添加下面的代碼: 
    [html] view plaincopy
    1. <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler">  
    2.     <property name="dataSource" ref="dataSource" />  
    3.     <property name="sql" value="select password from t_admin_user where login_name=?" />  
    4.     <property name="passwordEncoder" ref="MD5PasswordEncoder"/>  
    5. </bean>  


    在文件的末尾之前加入如下代碼:

    [html] view plaincopy
    1. <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">  
    2.    <property name="driverClassName"><value>com.mysql.jdbc.Driver</value></property>  
    3.    <property name="url"><value>jdbc:mysql:///wsriademo</value></property>  
    4.    <property name="username"><value>root</value></property>  
    5.    <property name="password"><value>root</value></property>  
    6. </bean>  
    7.    
    8. <bean id="MD5PasswordEncoder" class="org.jasig.cas.authentication.handler.DefaultPasswordEncoder">    
    9.     <constructor-arg index="0">  
    10.         <value>MD5</value>  
    11.     </constructor-arg>  
    12. </bean>  



     

  3. 複製cas-server-3.4.3.1\modules\cas-server-support-jdbc-3.4.3.1.jar和mysql驅動jar包到tomcat/webapp/cas/WEB-INF/lib目錄
  4. 配置解釋:
    • QueryDatabaseAuthenticationHandler是cas-server-support-jdbc提供的查詢接口其中一個,QueryDatabaseAuthenticationHandler是通過配置一個 SQL 語句查出密碼,與所給密碼匹配
    • dataSource我就不用解釋了吧,就是使用JDBC查詢時的數據源
    • sql語句就是查詢哪一張表,本例根據t_admin_user表的login_name字段查詢密碼,CAS會匹配用戶輸入的密碼,如果匹配則通過;下面是t_admin_user的表結構: 
      1. CREATE TABLE t_admin_user (  
      2.     id BIGINT NOT NULL AUTO_INCREMENT,  
      3.     email VARCHAR(255),  
      4.     login_name VARCHAR(255) NOT NULL UNIQUE,  
      5.     name VARCHAR(255),  
      6.     password VARCHAR(255),  
      7.     PRIMARY KEY (id)  
      8. ) ENGINE=InnoDB;  


    • passwordEncoder,這個就算是自己加的鹽巴了,意思很明顯就是處理密碼的加密,看你的應用中數據庫保存的是明碼還是加密過的,比如本例是使用MD5加密的,所以配置了MD5PasswordEncoder這個Handler,cas內置了MD5的功能所以只需要配置一下就可以了;如果在實際應用中使用的是公司自己的加密算法那麼就需要自己寫一個Handler來處理密碼,實現方式也比較簡單,創建一個類繼承org.jasig.cas.authentication.handler.PasswordEncoder然後在encode方法中加密用戶輸入的密碼然後返回即可

八、配置CAS客戶端

  1. 添加cas-client的jar包,有兩種方式:
    • 傳統型:下載cas-client,地址:http://www.ja-sig.org/downloads/cas-clients/,然後解壓cas-client-3.1.12.zip,在modules文件夾中有需要的jar包,請根據自己的項目情況選擇使用
    • Maven: 
      [html] view plaincopy
      1. <!-- cas -->  
      2. <dependency>  
      3.     <groupId>org.jasig.cas.client</groupId>  
      4.     <artifactId>cas-client-core</artifactId>  
      5.     <version>3.1.12</version>  
      6. </dependency>  

  2. 設置filter
    先上配置信息:
    [html] view plaincopy
    1. <!-- 用於單點退出,該過濾器用於實現單點登出功能,可選配置-->  
    2. <listener>  
    3.     <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>  
    4. </listener>  
    5.    
    6. <!-- 該過濾器用於實現單點登出功能,可選配置。 -->  
    7. <filter>  
    8.     <filter-name>CAS Single Sign Out Filter</filter-name>  
    9.     <filter-class>org.jasig.cas.client.session.SingleSignOutFilter</filter-class>  
    10. </filter>  
    11. <filter-mapping>  
    12.     <filter-name>CAS Single Sign Out Filter</filter-name>  
    13.     <url-pattern>/*</url-pattern>  
    14. </filter-mapping>  
    15.    
    16. <!-- 該過濾器負責用戶的認證工作,必須啓用它 -->  
    17. <filter>  
    18.     <filter-name>CASFilter</filter-name>  
    19.     <filter-class>org.jasig.cas.client.authentication.AuthenticationFilter</filter-class>  
    20.     <init-param>  
    21.         <param-name>casServerLoginUrl</param-name>  
    22.         <param-value>https://sso.wsria.com:8443/cas/login</param-value>  
    23.         <!--這裏的server是服務端的IP-->  
    24.     </init-param>  
    25.     <init-param>  
    26.         <param-name>serverName</param-name>  
    27.         <param-value>http://localhost:10000</param-value>  
    28.     </init-param>  
    29. </filter>  
    30. <filter-mapping>  
    31.     <filter-name>CASFilter</filter-name>  
    32.     <url-pattern>/*</url-pattern>  
    33. </filter-mapping>  
    34.    
    35. <!-- 該過濾器負責對Ticket的校驗工作,必須啓用它 -->  
    36. <filter>  
    37.     <filter-name>CAS Validation Filter</filter-name>  
    38.     <filter-class>  
    39.         org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter</filter-class>  
    40.     <init-param>  
    41.         <param-name>casServerUrlPrefix</param-name>  
    42.         <param-value>https://sso.wsria.com:8443/cas</param-value>  
    43.     </init-param>  
    44.     <init-param>  
    45.         <param-name>serverName</param-name>  
    46.         <param-value>http://localhost:10000</param-value>  
    47.     </init-param>  
    48. </filter>  
    49. <filter-mapping>  
    50.     <filter-name>CAS Validation Filter</filter-name>  
    51.     <url-pattern>/*</url-pattern>  
    52. </filter-mapping>  
    53.    
    54. <!--  
    55.     該過濾器負責實現HttpServletRequest請求的包裹,  
    56.     比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登錄用戶的登錄名,可選配置。  
    57. -->  
    58. <filter>  
    59.     <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
    60.     <filter-class>  
    61.         org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>  
    62. </filter>  
    63. <filter-mapping>  
    64.     <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>  
    65.     <url-pattern>/*</url-pattern>  
    66. </filter-mapping>  
    67.    
    68. <!--  
    69.     該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取用戶的登錄名。  
    70.     比如AssertionHolder.getAssertion().getPrincipal().getName()。  
    71. -->  
    72. <filter>  
    73.     <filter-name>CAS Assertion Thread Local Filter</filter-name>  
    74.     <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</filter-class>  
    75. </filter>  
    76. <filter-mapping>  
    77.     <filter-name>CAS Assertion Thread Local Filter</filter-name>  
    78.     <url-pattern>/*</url-pattern>  
    79. </filter-mapping>  
    80.    
    81. <!-- 自動根據單點登錄的結果設置本系統的用戶信息 -->  
    82. <filter>  
    83.     <display-name>AutoSetUserAdapterFilter</display-name>  
    84.     <filter-name>AutoSetUserAdapterFilter</filter-name>  
    85.     <filter-class>com.wsria.demo.filter.AutoSetUserAdapterFilter</filter-class>  
    86. </filter>  
    87. <filter-mapping>  
    88.     <filter-name>AutoSetUserAdapterFilter</filter-name>  
    89.     <url-pattern>/*</url-pattern>  
    90. </filter-mapping>  
    91. <!-- ======================== 單點登錄結束 ======================== -->  


     

    每個Filter的功能我就不多說了,都有註釋的,關鍵要解釋一下AutoSetUserAdapterFilter的作用和原理.
    查看完整的web.xml請猛擊這裏(Google code)

  3. 利用AutoSetUserAdapterFilter自動根據CAS信息設置Session的用戶信息
    先看一下這個Filter的源碼
    好的,如果你是老程序員應該很快就清楚Filter的目的,如果不太懂我再講解一下;
    主要是通過CAS的_const_cas_assertion_獲取從CAS服務器登陸的用戶名,然後再根據系統內部的用戶工具(UserUtil.java)來判斷是否已經登錄過,如果沒有登錄根據登錄名從數據庫查詢用戶信息,最後使用設置把用戶信息設置到當前session中。
    這樣就把用戶信息保存到了Sessino中,我們就可以通過UserUtil工具來獲取當前登錄的用戶了,我在實例項目中也加入了此功能演示,請看代碼:main.jsp的第44行處
  4. 補充一下:如果是爲一個老項目添加單點登錄功能,那麼基本不需要其他的修改,設置好上面的filter即可;當然最好獲取用戶信息的地方都調用一個工具類,統一管理不容易出錯。

九、美化CAS服務器界面

CAS服務端(cas-server)的界面只能在測試的時候用一下,真正系統上線肯定需要定製開發自己的頁面,就想網易CSDN的統一認證平臺一樣,所有子系統的認證都通過此平臺來轉接,大家可以根據他們的頁面自己定製出適合所屬應用或者公司的界面;簡單介紹一下吧,複製cas\WEB-INF\view\jsp\default\ui的一些JSP文件,每一個文件的用途文件名已經區分了,自己修改了替換一下就可以了。
例如:
登錄界面:casLoginView.jsp
登錄成功:casGenericSuccess.jsp
登出界面:casLogoutView.jsp

十、結束語

花了一下午時間終於寫完了,總共十項也算完美了。
現在看來起始利用CAS實現單點登錄其實不難,不要畏懼,更不要排斥!
本教程後面的代碼部分均來自本博客wsria-demo項目分支wsria-demo-sso
和本教程相關資料下載

  1. 本教程使用的演示程序,點擊這裏下載
  2. 使用keytool生成的key和證書,點擊這裏下載
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章