CAS单点登进SSO配置说明
安装环境
- 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