CAS單點登入SSO配置說明

安裝環境

常用命令

-genkey:在用戶主目錄創建一個默認文件“.keystore”,還會產生一個mykey的別名,makey中包含用戶的公鑰、私鑰和證書
-alias:產生別名
-keystore:指定密鑰庫的名稱
-keyalg:指定密鑰的算法
-validity:指定創建證書有效期多少天
-keysize:指定密鑰長度
-storepass:指定密鑰庫的密碼
-keypass:指定別名條目的密碼
-dname:指定證書擁有者信息
-list:顯示密鑰庫中證書信息
-v:顯示密鑰庫中證書的詳細信息
-export:將別名指定的證書導出到文件
-file:參數指定導出的文件到文件名
-delete:刪除密鑰庫中某條目
-keypasswd:修改密鑰庫中指定條目口令
-import:將已簽名數字證書導入密鑰庫

創建證書

證書是單點登錄認證系統中很重要的一把鑰匙,客戶端於服務器的交互安全靠的就是證書,這裏使用JDK自帶的keytools工具生成證書,

如果以後真正在產品環境中使用肯定要去證書提供商去購買。

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

keytool -genkey -alias cas -keyalg RSA -keystore f:/resources/cas



輸入完信息之後,輸入 y,然後輸入密碼,提交。

這裏,由於我的名稱輸入的是sso.rying.com,其實這個域名是不存在的,修改

C:\Windows\System32\drivers\etc\hosts

添加內容如下:

127.0.0.1  sso.rying.com

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


導出證書

dos下進入f:/resources目錄,

F:\resources>keytool -export -file f:/resources/cas.crt -alias wsria -keystore f:/resources/cas

輸入密碼,提交。



客戶端JVM導入證書

keytool -import -keystore E:\develop\Java\jdk1.6.0_37\jre\lib\security\cacerts -file f:\resources\cas.crt -alias cas


如果發生錯誤

嘗試使用密碼 changeit

至此證書的創建、導出、導入到客戶端JVM都已完成


應用到tomcat

修改tomcat,conf/server.xml文件
<!-- Define a SSL HTTP/1.1 Connector on port 8443
         This connector uses the JSSE configuration, when using APR, the
         connector should be using the OpenSSL style configuration
         described in the APR documentation -->
    
    <Connector port="8443" protocol="HTTP/1.1" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" keystoreFile="F:/resources/cas" keystorePass="root123" />

但是修改之後,發現tomcat啓動報錯:
嚴重: Failed to initialize end point associated with ProtocolHandler ["http-apr-8443"]
java.lang.Exception: Connector attribute SSLCertificateFile must be defined when using SSL with APR
	at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:494)
	at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:610)
	at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:429)
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:981)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:814)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:633)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:658)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
2013-2-19 10:30:25 org.apache.catalina.core.StandardService initInternal
嚴重: Failed to initialize connector [Connector[HTTP/1.1-8443]]
org.apache.catalina.LifecycleException: Failed to initialize component [Connector[HTTP/1.1-8443]]
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:106)
	at org.apache.catalina.core.StandardService.initInternal(StandardService.java:559)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.core.StandardServer.initInternal(StandardServer.java:814)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:633)
	at org.apache.catalina.startup.Catalina.load(Catalina.java:658)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
	at java.lang.reflect.Method.invoke(Method.java:597)
	at org.apache.catalina.startup.Bootstrap.load(Bootstrap.java:281)
	at org.apache.catalina.startup.Bootstrap.main(Bootstrap.java:450)
Caused by: org.apache.catalina.LifecycleException: Protocol handler initialization failed
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:983)
	at org.apache.catalina.util.LifecycleBase.init(LifecycleBase.java:102)
	... 12 more
Caused by: java.lang.Exception: Connector attribute SSLCertificateFile must be defined when using SSL with APR
	at org.apache.tomcat.util.net.AprEndpoint.bind(AprEndpoint.java:494)
	at org.apache.tomcat.util.net.AbstractEndpoint.init(AbstractEndpoint.java:610)
	at org.apache.coyote.AbstractProtocol.init(AbstractProtocol.java:429)
	at org.apache.catalina.connector.Connector.initInternal(Connector.java:981)
	... 13 more

原因是Tomcat提供了兩個SSL實現,一個是JSSE實現,另外一個是APR實現。
Tomcat將自動選擇使用哪個實現,即如果安裝了APR則自動選擇APR,否則選擇JSSE。
6.0默認使用JSSE實現,而7.0則使用APR實現。所以修改server.xml
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
               maxThreads="150" scheme="https" secure="true"
               clientAuth="false" sslProtocol="TLS" keystoreFile="F:/resources/cas" keystorePass="root123" />

啓動tomcat,一切正常,訪問https://sso.rying.com:8443/,打開:

點擊繼續,進入tomcat歡迎頁面,OK。

CAS服務器配置

下載完成後解壓到 F:\resources,把 F:\resources\cas-server-3.5.1\modules\cas-server-webapp-3.5.1.war 重命名爲cas.war,複製到tomcat webapp下面
訪問 https://sso.rying.com:8443/cas/login,看到登入頁面:

用戶名密碼相同就能登入成功了。 

CAS鏈接數據源登入配置

上面的初體驗僅僅是簡單的身份驗證,實際應用中肯定是要讀取數據庫的數據,下面我們來進一步配置CAS服務器怎麼讀取數據庫的信息進行身份驗證。首先打開

tomcat/webapp/cas/WEB-INF/deployerConfigContext.xml

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

把這個簡單登入驗證註釋掉,修改

<bean class="org.jasig.cas.adaptors.jdbc.QueryDatabaseAuthenticationHandler"> 
	<property name="dataSource" ref="dataSource"></property> 
	<property name="sql" value="select password from user where username=?"></property> 
</bean>

最後在配置文件末尾前加上

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
		<property name="driverClassName">
			<value>com.mysql.jdbc.Driver</value>
		</property>
		<property name="url">
			<value>jdbc:mysql://localhost:3306/test?autoReconnect=true&useUnicode=true&characterEncoding=utf-8</value>
		</property>
		<property name="username"><value>root</value></property>
		<property name="password"><value>root</value></property>
		<property name="defaultAutoCommit"><value>false</value></property>
</bean>
表:

-- ----------------------------
-- Table structure for `user`
-- ----------------------------
DROP TABLE IF EXISTS `user`;
CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(100) DEFAULT NULL,
  `password` varchar(100) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=utf8;

-- ----------------------------
-- Records of user
-- ----------------------------
INSERT INTO `user` VALUES ('1', 'irwin', '123');
INSERT INTO `user` VALUES ('2', 'janey', '456');
INSERT INTO `user` VALUES ('3', 'harris', '789');
INSERT INTO `user` VALUES ('4', 'howard', '110');
INSERT INTO `user` VALUES ('5', 'morris', '888');
INSERT INTO `user` VALUES ('6', 'stephen', '999');
INSERT INTO `user` VALUES ('7', 'linsay', '000');
INSERT INTO `user` VALUES ('8', 'lilian', '111');
INSERT INTO `user` VALUES ('9', 'perry', '666');
INSERT INTO `user` VALUES ('10', 'laura', 'eeee');
INSERT INTO `user` VALUES ('20', 'www', 'ddd');
INSERT INTO `user` VALUES ('21', 'dd', 'dd');

賦值 F:\resources\cas-server-3.5.1\modules\cas-server-support-jdbc-3.5.1.jar 到 tomcat/webapp/cas/WEB-INF/lib目錄

這裏由於我使用的DBCP數據源,需要加入相應的jar包,如果使用其他數據源,加入相應的jar包即可。

使用現在數據庫存在的數據登入成功:



配置說明:

QueryDatabaseAuthenticationHandler:cas-server-support-jdbc提供的查詢接口其中一個,QueryDatabaseAuthenticationHandler是通過配置一個 SQL 語句查出密碼,與所給密碼匹配。

如果需要使用密碼加密,可以創建一個類繼承 org.jasig.cas.authentication.handler.PasswordEncoder,然後在encode中加密用戶輸入的密碼返回即可。

如果需要在代碼中獲取用戶名密碼進行驗證,可以創建一個類繼承 org.jasig.cas.authentication.handler.support.AbstractUsernamePasswordAuthenticationHandler,重寫

authenticateUsernamePasswordInternal方法。

CAS客戶端配置

eclipse下新建一個web項目,從F:\resources\cas-client-3.2.1\modules導入jar包
cas-client-core-3.2.1.jar
commons-logging-1.1.jar
配置web.xml,添加以下內容:
 <!-- 登出 -->
    <listener>
        <listener-class>org.jasig.cas.client.session.SingleSignOutHttpSessionListener</listener-class>
    </listener>
    
    <!-- 登出 ,改filter要在其他filter之前-->
    <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.rying.com:8443/cas/login</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://localhost:8080</param-value>
        </init-param>
    </filter>
    
    <!-- 請求參數ticket驗證(ticket即子系統與CAS系統進行交互的憑證) -->
    <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.rying.com:8443/cas</param-value>
        </init-param>
        <init-param>
            <param-name>serverName</param-name>
            <param-value>http://localhost:8080</param-value>
        </init-param>
    </filter>

    <!--
    該過濾器負責實現HttpServletRequest請求的包裹,
    比如允許開發者通過HttpServletRequest的getRemoteUser()方法獲得SSO登錄用戶的登錄名,可選配置。
    -->
    <filter>
        <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>
        <filter-class>org.jasig.cas.client.util.HttpServletRequestWrapperFilter</filter-class>
    </filter>
    
    <!--
    該過濾器使得開發者可以通過org.jasig.cas.client.util.AssertionHolder來獲取用戶的登錄名。
    比如AssertionHolder.getAssertion().getPrincipal().getName()。
    -->
    <filter>
        <filter-name>CAS Assertion Thread Local Filter</filter-name>
        <filter-class>org.jasig.cas.client.util.AssertionThreadLocalFilter</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 Wrapper Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>
    
        <filter-mapping>
        <filter-name>CAS Assertion Thread Local Filter</filter-name>
        <url-pattern>/*</url-pattern>
    </filter-mapping>


WebContent下創建測試頁面,hello.html
啓動服務器,瀏覽器訪問 http://localhost:8080/CASClient/hello.html


頁面跳轉到CAS系統登入頁面,輸入用戶名密碼

登入成功,返回hello.html頁面,並且帶上了jsessionid。

注意:這裏可能會拋出異常 sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
解決辦法:導入證書到jre中,方法同導入到jdk中的jre。
keytool -import -keystore E:\develop\Java\jre6\lib\security\cacerts -file f:\resources\cas.crt -alias cas
看下是否添加成功:keytool -list -keystore E:\develop\Java\jre6\lib\security\cacerts


此時,再創建一個CASClient2,項目同CASClient,使用CASClient訪問hello.html並且登入成功之後,我們訪問CASClient2的hello.html

可以看到同樣帶上了jsessionid,登入成功。

訪問 https://sso.rying.com:8443/cas/logout 測試註銷,出現註銷成功頁面,OK。
如果註銷成功想回到登入頁面,可以修改cas-servlet.xml文件,在logoutController的bean配置中修改
p:followServiceRedirects="${cas.logout.followServiceRedirects:false} 爲 true
修改 logout路徑,並加上service屬性,爲需要重定向頁面地址
原來路徑:https://sso.rying.com:8443/cas/logout 
現在:https://sso.rying.com:8443/cas/logout ?service=http://localhost:8080/CASClient/login.html

界面美化

CAS服務器登入頁面在\webapps\cas\WEB-INF\view\jsp\default\ui下
  • 登入頁面:casLoginView.jsp
  • 登入成功頁面:casGenericSuccess.jsp
  • 登出頁面:casLogoutView.jsp
自己修改替換這些文件就可以了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章