安裝環境
- Tomcat7.0
- JDK6
- CAS SERVER 3.5.1,下載地址 http://www.jasig.org/cas/download
- CAS CLIENT 3.2.1,下載地址 http://downloads.jasig.org/cas-clients/?C=M;O=D
常用命令
創建證書
證書是單點登錄認證系統中很重要的一把鑰匙,客戶端於服務器的交互安全靠的就是證書,這裏使用JDK自帶的keytools工具生成證書,
如果以後真正在產品環境中使用肯定要去證書提供商去購買。
用JDK自帶的keytool工具生成證書:
keytool -genkey -alias cas -keyalg RSA -keystore f:/resources/cas
輸入完信息之後,輸入 y,然後輸入密碼,提交。
C:\Windows\System32\drivers\etc\hosts
添加內容如下:
127.0.0.1 sso.rying.com
這樣在訪問sso.rying.com的時候其實是訪問的127.0.0.1也就是本機
導出證書
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
至此證書的創建、導出、導入到客戶端JVM都已完成
應用到tomcat
<!-- 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
<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" />
CAS服務器配置
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客戶端配置
<!-- 登出 -->
<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>
啓動服務器,瀏覽器訪問 http://localhost:8080/CASClient/hello.html
界面美化
- 登入頁面:casLoginView.jsp
- 登入成功頁面:casGenericSuccess.jsp
- 登出頁面:casLogoutView.jsp