1. 程式人生 > >CAS實現的單點登入系統

CAS實現的單點登入系統

單點登入(single sign on ),簡稱SSO

純屬學習用,對來自網路的部分如果侵害了您的權力,請聯絡我。QQ:262800095

SSO的定義是在多個應用系統中,使用者只需要登入一次就可以訪問所有相互信任的應用系統,而不需要重新登入。

用一個現實中的例子做比較。頤和園是北京著名的旅遊景點,也是我常去的地方。在頤和園內部有許多獨立的景點,例如蘇州街佛香閣德和園,都可以在各個景點門口單獨買票。很多遊客需要遊玩所有德景點,這種買票方式很不方便,需要在每個景點門口排隊買票,錢包拿進拿出的,容易丟失,很不安全。於是絕大多數遊客選擇在大門口買一張通票(也叫套票),就可以玩遍所有的景點而不需要重新再買票。他們只需要在每個景點門口出示一下剛才買的套票就能夠被允許進入每個獨立的景點。

單點登入的機制也一樣,如下圖所示,當用戶第一次訪問應用系統1的時候,因為還沒有登入,會被引導到認證系統中進行登入(1);根據使用者提供的登入資訊,認證系統進行身份效驗,如果通過效驗,應該返回給使用者一個認證的憑據--ticket2);使用者再訪問別的應用的時候(35)就會將這個ticket帶上,作為自己認證的憑據,應用系統接受到請求之後會把ticket送到認證系統進行效驗,檢查ticket的合法性(46)。如果通過效驗,使用者就可以在不用再次登入的情況下訪問應用系統2和應用系統3了。

 

要實現SSO,需要實現以下主要的功能:

所有的應用系統共享一個身份認證系統。

統一的身份認證系統是SSO

的前提,認證系統的主要功能是將使用者的登入資訊和使用者資訊庫相比較,對使用者進行登入認證。認證成功後,認證系統應該生成統一的認證標誌(ticket),返還給使用者。另外,認證系統還應該對ticket進行效驗,判斷其有效性。

所有應用系統能夠識別和提取ticket資訊

要實現SSO的功能,讓使用者只登入一次,就必須讓應用系統能夠識別已經登入過的使用者。應用系統應該能對ticket進行識別和提取,通過與認證系統的通訊,能自動判斷當前使用者是否登入過,從而完成單點登入的功能。

以上內容都來自網路。

如何使用CAS實現單點登入

一、簡介

CASCentral Authentication Server

中央驗證系統)是耶魯大學研發的單點登入系統。系統為了安裝考慮預設是需要證書驗證的。

本人使用的環境為:

apache-tomcat-6.0.30(原來用的是tomcat7,但中途遇到了8443埠無法驗證的問題,懷疑是版本的原因,因此換成了tomcat6PS:最後找出了原因是域名的問題,後面將會提到)

JDK6

CAS Server版本:cas-server-3.4.2-release(下載地址:http://downloads.jasig.org/cas/)解壓後,會發現一個modules資料夾,裡面包含了配置CAS server所需要的jar包和war檔案。

)解壓後,會發現一個moudules資料夾,裡面包含了配置CAS Client所需要的jar包。

PS:選擇低版本的客戶端可能會出現少jar包的情況。

二、安裝證書:

1、JDK自帶的keytool生成證書

keytool -genkey -alias  smalllove -keyalg RSA -keystore D:/keys/smallkey

這一步尤其要注意的是對名字與姓氏的填寫:不要寫localhost或者其他的什麼東西,最好是寫域名,比如我輸入localhost的話,後面8443埠就訪問不到系統了,就這個問題我弄了一天時間才發現。所以,最好是輸入一個域名,然後修改C:\Windows\System32\drivers\etc\hosts檔案,在裡面新增對映。

 

2、匯出證書:

keytool -export -file d:/keys/small.crt -alias smalllove -keystore d:/keys/smallkey

3、將證書匯入到JDK

進入C:\Program Files\Java\jdk1.6.0_24\jre\lib\security目錄

keytool -import -keystore cacerts -file D:/keys/small.crt -alias smalllove

此處如果某個資料夾包含了空格的話,絕對路徑是不行的。剛開始我根據網上的資料,用絕對路勁來定位,總是出現錯誤,後來仔細看菜發現時我的Program Files目錄裡有空格。所以必須進入到這個目錄下,否則會出現錯誤。

三、HTTPS訪問CAS

CAS Server解壓出來的war檔案部署到eclipse裡面。

tomcatserver.xml的配置修改一下,

<Connectorport="8443"protocol="HTTP/1.1"SSLEnabled="true"

              maxThreads="150"scheme="https"secure="true"

              clientAuth="false"sslProtocol="TLS"

              keystoreFile="D:/keys/smallkey"

              keystorePass="123456"/>

注意一定要改對地方,如果是用eclipse配置的tomcat就在對應的伺服器的檔案裡改。比如我war檔案的部署在tomcat v6.0 server at localhost伺服器上,就應該改的tomcat v6.0 server at localhost-config裡的server.xml

可以點選繼續瀏覽或者將證書安裝到信任區裡。

然後輸入相同的賬戶密碼就OK。如果進入系統後顯示登入成功頁面,並且在位址列裡給出了seddionid=…說明CAS Service已經安裝成功。否則的話自己找問題吧^_^

四、客戶端的配置。

完成了服務端,現在我們來解決客戶端。

新建一個兩個web工程myapp1myapp2,然後修改其web.xml如下:

<?xmlversion="1.0"encoding="UTF-8"?>

<web-appxmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xmlns="http://java.sun.com/xml/ns/javaee"xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"id="WebApp_ID"version="2.5">

<display-name>myapp2</display-name>

<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.wsria.com:8443/cas/</param-value>

</init-param>

<init-param>

<param-name>serverName</param-name>

<param-value>http://localhost:8082</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>CAS Authentication Filter</filter-name>

    <url-pattern>/*</url-pattern>

</filter-mapping>

<welcome-file-list>

<welcome-file>index.jsp</welcome-file>

</welcome-file-list>

</web-app>

我特地將myapp2放在了另外一個tomcat伺服器裡面,並改了埠。

引入jar包:cas-client-core-3.2.1.jarcommons-logging-1.1.jar。將這兩個包複製到lib目錄下即可,如果用build path裡的add external jar來加入這兩個jar包就會提示class not found的錯誤。

此時,登入myapp1就會跳轉到CAS Server的驗證介面,輸入相同的使用者名稱密碼,進入myapp1,然後再進入myapp2,此時就不需要驗證了。

五、通過資料庫和CAS系統一起實現單點登入

1、伺服器的配置

我安裝的是mysql5.5,這個就不用說了……安裝完成之後,建立一個名為usr_info的資料庫。然後建表並插入資料:

create table usr(name char(20) not null,password char(20) not null);

insert into usr values("test1" ,"123456");

insert into usr values("test2" ,"223456");

cas-server-3.4.2裡的modulescas-server-support-jdbc-3.4.2.jarjdbc連線mysqlmysql-connector-java-5.1.18-bin.jar複製到cas專案的WEB-INFlib目錄下。

修改WEB-INF目錄下的deployerConfigContext.xml檔案,將

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

遮蔽掉,然後加入以下配置檔案:

<beanclass="org.jasig.cas.adaptors.jdbc.SearchModeSearchDatabaseAuthenticationHandler"

             abstract="false"lazy-init="default"autowire="default">

<propertyname="tableUsers">

<value>usr</value>

</property>

<propertyname="fieldUser">

<value>name</value>

</property>

<propertyname="fieldPassword">

<value>password</value>

</property>

<propertyname="dataSource"ref="dataSource"/>

</bean>

上面這段配置檔案主要是新增對使用者名稱和密碼的校驗工作,常用的有三種校驗方式

l SimpleTestUsernamePasswordAuthenticationHandler

這個就是預設的簡單的使用者名稱密碼校驗,只要使用者名稱和密碼相同就能登入。

l QueryDatabaseAuthenticationHandler

這個是用select語句來驗證,具體配置檔案可以參考網上寫的。我剛開始時用這種方法,但每次儘管輸入的使用者名稱和密碼是正確的,還會提示failed to authenticate the user which provided the following credentialstest1,所以我後來改用了指定表和欄位來連線。這是一個很容易讓人很糾結的問題。

l SearchModeSearchDatabaseAuthenticationHandler

這個是通過指定表盒欄位來連線資料庫,也就是我的配置檔案裡選用的連線方法。

最後,在檔案的末尾加上以下配置檔案:

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

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

  <propertyname="url"><value>jdbc:mysql:///usr_info</value></property>

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

  <propertyname="password"><value>123</value></property>

</bean>

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

<constructor-argindex="0">

<value>MD5</value>

</constructor-arg>

</bean>

上面的這段配置檔案實際上就是配置資料來源和加密演算法,很容易理解。

2、客戶端的配置

myapp1myapp2web.xml配置檔案里加入如下的filter

<!--該過濾器負責對Ticket的校驗工作,必須啟用它-->

<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.wsria.com:8443/cas</param-value>

</init-param>

<init-param>

<param-name>serverName</param-name>

<param-value>http://localhost:8081</param-value>

</init-param>

</filter>

<filter-mapping>

<filter-name>CAS Validation Filter</filter-name>

<url-pattern>/*</url-pattern>

</filter-mapping>

這樣就完成了客戶端的配置。執行伺服器和兩個客戶端,發現輸入adminadmin已經不能登入系統。只有當輸入使用者名稱:test1,密碼:123456時才能登入。

PSCAS提供的所謂的記憶體cookie。也就是,如果將所有的瀏覽器關閉,那麼CAScookie會自動消失,需要重新登入。OK 功能完成!

六、客戶端接收引數,以及取得當前登入的使用者名稱

如果我在myapp1系統裡有如下超連結:

<a href="http://localhost:8082/myapp2/index.jsp?value=hello">進入myapp2,並攜帶引數value=hello </a>

當某個超連結攜帶引數經過CAS驗證後,會不會使得引數丟失呢?答案是不會。並且,其接受引數的方法與沒有整合CAS系統的方法一模一樣。

那麼,在客戶端又應該如何獲得當前登入使用者的使用者名稱呢?

<%@page import="org.jasig.cas.client.util.AbstractCasFilter"%>

<%@page import="org.jasig.cas.client.validation.Assertion"%>

<%

Assertion assertion1=(Assertion)session.getAttribute(AbstractCasFilter.CONST_CAS_ASSERTION);

String username = assertion1.getPrincipal().getName();

%>

Usernam就是當前登入使用者的使用者名稱。

到這裡就告一段落了先。

以後將會進一步研究如何在CAS裡實現許可權的管理,比如test1使用者只對A系統和B系統有訪問許可權,而對C系統沒有訪問許可權,那麼test1在登入過A系統之後,進入B系統就不需要驗證了,進入C系統的話還是需要驗證。可現在是不管進入哪個系統都不需要驗證。那又應該去如何設定呢?