CAS是YALE大學發起的一個開源項目,旨在為web應用系統提供一種可靠的單點登錄方法。它主要分為client和server端,server端負責對用戶的認證工作,client端負責處理對客戶端受保護的資源的訪問請求,CAS的原理如下圖所示:
上述的6個步驟解釋如下:
1.用戶通過browser請求cas client A端的資源。
2.client A端發現用戶未登錄(client沒有收到ST),redirect到cas server,並且把用戶請求服務的url發送給server;server發現用戶瀏覽器中沒有TGC(Ticket Granting Cookie),就跳轉到登錄頁面。
3.用戶在登錄頁面登錄並登錄成功。
4.server在用戶的瀏覽器中設置一個TGC(Ticket Granting Cookie),並且在server端保存一個TGT(Ticket Granting Tciket),然后把用戶重定向到{client A網址+ST(Service Ticket)},其中ST是由TGT生成的。
5.client A端通過GET的方法收到ST,向server端驗證這個ticket的有效性,這一步主要是為了防止惡意用{client網址+杜撰的ST}來訪問client A,所以雖然ST是server發送給client A的,client A仍然需要向server驗證其有效性。
6.ticket有效,server端返回ticket對應的用戶的用戶名,client A端為用戶提供請求的服務。
上述是未登錄的用戶訪問client A的過程,用戶通過以上步驟已經登錄了CAS系統,此時他訪問CAS系統中信任的client B端,是不用登錄的,實現步驟如下:
1.1.用戶通過browser請求cas client B端的資源。
2.client B端發現沒有收到ST,redirect到cas server,並且把用戶請求服務的url發送給server;server發現用戶瀏覽器中有TGC(Ticket Granting Cookie),驗證該TGC后,用server端存儲的TGT生成一個ST。
3.server把用戶重定向到{client B網址+ST(Service Ticket)}。
4.client B端通過GET的方法收到ST,向server端驗證這個ticket的有效性.
5.ticket有效,server端返回ticket對應的用戶的用戶名,client B端為用戶提供請求的服務,這樣用戶就不用再次登錄就可以訪問到client B了。
所以從上述過程中,可以看到client端既不能接觸到用戶的用戶名密碼,也不能接觸到用戶的憑證TGT或者TGC,它只做兩件事情:如果用戶的請求里有ST,那么就向服務器驗證ST的有效性;如果用戶的請求里沒有ST,那么就把用戶重定向到cas server;
cas server全權負責管理用戶的用戶名和密碼,如果發現用戶的瀏覽器里面有有效的TGC,就生成ST把用戶重定向到client端;如果用戶瀏覽器里面沒有TGC或者TGC無效,就讓用戶重新登錄,然后在用戶的瀏覽器里面設置新的TGC。而server和用戶瀏覽器之間的交互是https安全協議,這樣就保證了用戶的用戶名密碼的安全性。
本文記錄server端的搭建過程。
1.安裝JDK
2.搭建TOMCAT:
雙擊%TOMCAT_PATH%/bin/startup.bat啟動tomcat
瀏覽器打開http://localhost:8080,若顯示如下界面,則配置成功:
3.配置tomcat使用https協議
(1)生成安全證書
cd到%JAVA_HOME%/bin/目錄下,執行一下命令
keytool -genkeypair -alias "tomcat" -keyalg "RSA" -keystore "g:\tomcat.keystore"
其中"g:\tomcat.keystore"是保存生成證書的路徑和名稱。
在接下來的操作中,要注意的是“您的名字和姓氏是什么?”這里要回答域名,比如我是在本機搭建tomcat,所以回答localhost,如下圖所示:
其他的隨便填就好了,密碼當然要記住,我這里用的是"tomcat"作為密碼,后面配置的時候要用到的。
上述命令執行完后就可以在g:\下看到證書tomcat.keystore了。
(2)配置tomcat
在%TOMCAT_PATH%/conf下找到server.xml文件,定位到下面的代碼上:
<!-- <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true" maxThreads="150" scheme="https" secure="true" clientAuth="false" sslProtocol="TLS" /> -->
去掉注釋,然后把它修改成下面的代碼:
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" maxThreads="150" SSLEnabled="true" scheme="https" secure="true" keystoreFile="G:\tomcat.keystore" keystorePass="tomcat" clientAuth="false" sslProtocol="TLS" />
各項的含義見下表:
然后在瀏覽器里面打開https://localhost:8443,出現如下界面就說明配置tomcat使用https成功了:
4.配置CAS Server
到CAS主頁上下載cas server,我這里下載的並不是最新版,是cas-server-3.5.2-release.zip;然后解壓,到\cas-server-3.5.2\modules目錄下找到cas-server-webapp-3.5.2.war,把它拷貝到\apache-tomcat-7.0.56\webapps下並且重命名為cas.war,重啟tomcat(雙擊\apache-tomcat-7.0.56\bin\startup.bat),用瀏覽器打開https://localhost:8443/cas/login,如果出現一下界面則說明CAS Server配置成功:
5.與MYSQL連接
目前配置好的CAS的用戶名和密碼驗證十分簡單,既只要用戶名和密碼相同就可以登錄了。但在實際應用中我們的用戶名密碼常常是保存在數據庫里面的,所以我們希望實現從數據庫里面驗證用戶名和密碼。操作步驟如下:
(1)用phpMyAdmin在MYSQL中創建用戶名密碼的表,這里新建一個數據庫casuserdatabase,創建一張表app_user來存放用戶名密碼信息,然后插入兩條測試用的用戶名密碼,sql語句如下;
CREATE DATABASE casuserdatabase; USE casuserdatabase; CREATE TABLE app_user (username varchar(30), password varchar(45) , primary key (username)); INSERT INTO app_user (username,password) values ('test01','psw01'); INSERT INTO app_user (username,password) values('test02','psw02');
(2)到這里下載mysql-connector-java-5.1.22,其他版本的我沒有嘗試過,不知道可不可以。解壓,我們只需要文件夾里面的mysql-connector-java-5.1.22-bin.jar包。
到cas-server-3.5.2\modules\目錄下找到cas-server-support-jdbc-3.5.2.jar。
把上述兩個包拷貝到apache-tomcat-7.0.56\webapps\cas\WEB-INF\lib\目錄下。
(3)配置apache-tomcat-7.0.56\webapps\cas\WEB-INF\目錄下的deployerConfigContext.xml文件:
首先增加一個datasource,通過增加一下的代碼實現:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost/casuserdatabase"/> <property name="username" value="sunshineatnoon"/> <property name="password" value="49531218"/> </bean>
然后改變認證方式,定位到如下代碼:
<bean
class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" />
把它注釋掉,換成:
<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"> <property name="dataSource" ref="dataSource" /> <property name="sql" value="select password from app_user where userName=?" /> </bean>
其中<property name="sql" value="select password from app_user where userName=?" /> 中app_user是我存放用戶名和密碼的表,需要根據實際情況而定。
注意這里datasource放在注釋掉的那行代碼所在的</list>外面,大概相對位置見下面的代碼,否則會報錯:
<!--bean class="org.jasig.cas.authentication.handler.support.SimpleTestUsernamePasswordAuthenticationHandler" /--> <bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"> <property name="dataSource" ref="dataSource" /> <property name="sql" value="select password from app_user where userName=?" /> </bean> </list> </property> </bean> <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"></property> <property name="url" value="jdbc:mysql://localhost/casuserdatabase"/> <property name="username" value="sunshineatnoon"/> <property name="password" value="49531218"/> </bean>
(4)重啟tomcat,再次到登錄頁面https://localhost:8443/cas/login上,就可以用數據庫中的用戶名和密碼登錄了,比如這里用上面設置的"test01","psw01"登錄:
到這里還有個bug就是登錄的時候總是會清空一次登錄框,第二次才能登上去,研究下這個bug怎么解決再說。
還有一個是目前我還不知道怎么登出,於是就用最笨的方法,把瀏覽器的cookie刪掉,刷新登錄頁面,就算登出啦。
參考資料
[1]配置tomcat使用https:http://ln-ydc.iteye.com/blog/1330674
[2]與mysql連接配置:http://blog.sina.com.cn/s/blog_3fc815b30100ihtr.html
[3]mysql-connector-java-5.1.22下載:http://6881116.blog.51cto.com/6871116/1190148