San*_*ndy 4 ssl cas spring-security ssl-certificate single-sign-on
我正在使用中央身份验证系统(jasig.org)为我的Intranet Web应用程序实现单点登录功能.我在同一台机器(windows)中运行了两个tomcat实例.两个tomcat实例都已配置为使用SSL并使用了自签名sertificate(使用java keytool创建).
Cas Server.
<Connector port="8443" maxHttpHeaderSize="8192" SSLEnabled="true"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS"
keystoreFile="C:/Users/sandip.paul/.keystore"
keystorePass="changeit"
truststoreFile="C:/Program Files/Java/jdk1.6.0_20/jre/lib/security/cacerts" />
Run Code Online (Sandbox Code Playgroud)
myWebApp(使用spring security)
<Connector port="8663" maxHttpHeaderSize="8192" SSLEnabled="true"
maxThreads="150" minSpareThreads="25" maxSpareThreads="75"
enableLookups="false" disableUploadTimeout="true"
acceptCount="100" scheme="https" secure="true"
clientAuth="false" sslProtocol="TLS" />
Run Code Online (Sandbox Code Playgroud)
下面是myWebApp的applicationContext-security.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:security="http://www.springframework.org/schema/security"
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
<!--
Enable security, let the casAuthenticationEntryPoint handle all intercepted urls.
The CAS_FILTER needs to be in the right position within the filter chain.
-->
<security:http entry-point-ref="casProcessingFilterEntryPoint" auto-config="true">
<security:intercept-url pattern="/protected/**" access="IS_AUTHENTICATED_FULLY" />
</security:http>
<!--
Required for the casProcessingFilter, so define it explicitly set and
specify an Id Even though the authenticationManager is created by
default when namespace based config is used.
-->
<security:authentication-manager alias="authenticationManager" />
<!--
This section is used to configure CAS. The service is the
actual redirect Client URL that will be triggered after the CAS login sequence.
-->
<bean id="serviceProperties" class="org.springframework.security.ui.cas.ServiceProperties">
<property name="service" value="https://obll1973.abc.com:8663/myWebApp/j_spring_cas_security_check"/>
<property name="sendRenew" value="false"/>
</bean>
<!--
The customUserDetailsService provides ROLE & other Details and
create an object of UserDetail for this application.
-->
<bean id="customUserDetailsService"
class="edu.sandip.cas.client.authentication.CustomUserDetailsService">
</bean>
<!--
The CasProcessingFilter has very similar properties to the
AuthenticationProcessingFilter (used for form-based logins).
The CAS Processing filter handles the redirect from the CAS server
and starts the ticket validation.
-->
<bean id="casProcessingFilter" class="org.springframework.security.ui.cas.CasProcessingFilter">
<security:custom-filter after="CAS_PROCESSING_FILTER"/>
<property name="authenticationManager" ref="authenticationManager"/>
<property name="authenticationFailureUrl" value="/casfailed.jsp"/>
<property name="defaultTargetUrl" value="/"/>
</bean>
<!--
The entryPoint intercepts all the CAS authentication requests.
It redirects to the CAS loginUrl for the CAS login page.
-->
<bean id="casProcessingFilterEntryPoint"
class="org.springframework.security.ui.cas.CasProcessingFilterEntryPoint">
<property name="loginUrl" value="https://obll1973.abc.com:8443/cas/login"/>
<property name="serviceProperties" ref="serviceProperties"/>
</bean>
<!--
Handles the CAS ticket processing.
-->
<bean id="casAuthenticationProvider"
class="org.springframework.security.providers.cas.CasAuthenticationProvider">
<security:custom-authentication-provider />
<property name="userDetailsService" ref="customUserDetailsService" />
<property name="serviceProperties" ref="serviceProperties" />
<property name="ticketValidator">
<bean class="org.jasig.cas.client.validation.Cas20ServiceTicketValidator">
<constructor-arg index="0" value="https://obll1973.abc.com:8443/cas" />
</bean>
</property>
<property name="key" value="an_id_for_this_auth_provider_only"/>
</bean>
<!--
To access request.getRemoteUser() from client application
-->
<bean id="wrappingFilter" class="org.jasig.cas.client.util.HttpServletRequestWrapperFilter" />
</beans>
Run Code Online (Sandbox Code Playgroud)
我面临的问题是以下例外情况:
java.lang.RuntimeException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:341)
org.jasig.cas.client.util.CommonUtils.getResponseFromServer(CommonUtils.java:305)
org.jasig.cas.client.validation.AbstractCasProtocolUrlBasedTicketValidator.retrieveResponseFromServer(AbstractCasProtocolUrlBasedTicketValidator.java:50)
org.jasig.cas.client.validation.AbstractUrlBasedTicketValidator.validate(AbstractUrlBasedTicketValidator.java:207)
org.springframework.security.providers.cas.CasAuthenticationProvider.authenticateNow(CasAuthenticationProvider.java:145)
org.springframework.security.providers.cas.CasAuthenticationProvider.authenticate(CasAuthenticationProvider.java:131)
org.springframework.security.providers.ProviderManager.doAuthentication(ProviderManager.java:188)
org.springframework.security.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:46)
org.springframework.security.ui.cas.CasProcessingFilter.attemptAuthentication(CasProcessingFilter.java:94)
org.springframework.security.ui.AbstractProcessingFilter.doFilterHttp(AbstractProcessingFilter.java:258)
org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
org.springframework.security.ui.logout.LogoutFilter.doFilterHttp(LogoutFilter.java:89)
org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
org.springframework.security.context.HttpSessionContextIntegrationFilter.doFilterHttp(HttpSessionContextIntegrationFilter.java:235)
org.springframework.security.ui.SpringSecurityFilter.doFilter(SpringSecurityFilter.java:53)
org.springframework.security.util.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:390)
org.springframework.security.util.FilterChainProxy.doFilter(FilterChainProxy.java:175)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:236)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
Run Code Online (Sandbox Code Playgroud)
复制上述异常的步骤:1)我尝试使用https://obll1973.abc.com:8663/myWebApp/protected/访问myWebApp 2)它被重定向到cas服务器,即https://obll1973.abc.com: 8443/cas/login和提供用户名/密码后,一旦myWebApp再次向cas服务器发送请求以验证生成的令牌,就会捕获异常.
任何建议/帮助都会受到高度关注.
小智 8
你的Spring-CAS配置看起来很好.
出现SSLHandshakeException的唯一原因是由于不正确地将SSL密钥导入到创建的密钥库或JVM密钥库中.
注意:作为CN的别名(此处为cas)应与计算机的主机名相同.
要找到机器的主机名,在控制台或命令promt中只需键入"hostname",不带引号.
在root named app下创建一个目录
[root @ localhost app] #keytool -genkey -alias cas -keyalg RSA -keystore .cas -storepass caspasswd
你的名字和姓氏是什么?[Unknown]:cas您的组织单位名称是什么?[Unknown]:MYCOMPANY您的组织名称是什么?[未知]:MYCOMPANY您所在城市或地区的名称是什么?[未知]:班加罗尔您所在州或省的名称是什么?[Unknown]:Karnataka这个单位的双字母国家代码是什么?[Unknown]:IN CN = cas,OU = MYCOMPANY,O = MYCOMPANY,L = Bangalore,ST = Karnataka,C = IN正确吗?[不]:是的
输入密钥密码(给出上面提到的密码 - 在这种情况下是caspasswd)(如果与密钥库密码相同则返回):重新输入新密码:
[root @ localhost app] #keytool -exportcert -alias cas -file cas.crt -keystore .cas输入密钥库密码:存储在文件中的证书
[root @ localhost app] #ls cas.crt softwares test.class test.java tomcat7027CAS
[root @ localhost app] #keytool -import -alias cas -file cas.crt -keystore /app/softwares/jdk1.6.0_27/jre/lib/security/cacerts输入密钥库密码:所有者:CN = cas,OU = MYCOMPANY ,O = MYCOMPANY,L =班加罗尔,ST =卡纳塔克邦,C = IN发行人:CN = cas,OU = MYCOMPANY,O = MYCOMPANY,L =班加罗尔,ST =卡纳塔克邦,C = IN序列号:510a6a63有效自:Thu Jan 31 18:28:11 IST 2013直到:Wed May 01 18:28:11 IST 2013证书指纹:MD5:52:8E:2E:74:C6:57:CD:B3:B0:B6:6C:17:D9 :0D:77:F3 SHA1:1F:AA:4C:22:B9:16:DC:AA:D4:87:07:CF:DD:B2:11:A6:AE:36:9A:DB签名算法名称:SHA1withRSA版本:3信任此证书?[no]:是证书已添加到密钥库
[root @ localhost app] #keytool -list -keystore /app/softwares/jdk1.6.0_27/jre/lib/security/cacerts -alias cas输入密钥库密码:cas,2013年1月31日,trustedCertEntry,证书指纹(MD5) :52:8E:2E:74:C6:57:CD:B3:B0:B6:6C:17:D9:0D:77:F3
[root @ localhost app]#
在tomcat server.xml中,您还可以使用https连接器,如下所示
<Connector port="8443" protocol="org.apache.coyote.http11.Http11Protocol" SSLEnabled="true"
maxThreads="150" scheme="https" keystoreFile="/app/.cas" keystorePass="mykeypassword"
secure="true" connectionTimeout="240000"
clientAuth="false" sslProtocol="TLS" allowUnsafeLegacyRenegotiation="true" />
<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector port="8069" protocol="AJP/1.3" redirectPort="8443" />
Run Code Online (Sandbox Code Playgroud)
以上密钥用于CAS Server.您可以为应用程序创建自己的单独密钥.
但是这两个密钥都应该导入到JVM cacerts密钥库中(如何:在下面提到)
现在最重要的部分: 假设您的CAS服务器别名是cas
您的应用程序服务器别名是myapp
将两个服务器中的密钥cas.crt和myapp.crt保存到JVM中
在两个服务器中执行以下操作:
1)keytool -import -alias cas -file /app/cas.crt -keystore /usr/java/jdk1.5.0_22/jre/lib/security/cacerts
2)keytool -import -alias myapp -file /app/cas.crt-keystore /usr/java/jdk1.5.0_22/jre/lib/security/cacerts
要验证使用以下命令 -
1)keytool -list -v -keystore /usr/java/jdk1.5.0_22/jre/lib/security/cacerts -alias cas
2)keytool -list -v -keystore /usr/java/jdk1.5.0_22/jre/lib/security/cacerts -alias myapp
如果使用多个版本的java,请确保Java-JRE-LIB-SECURITY-CACERTS文件
这将删除您的错误.
注意 :
如果在给出正确的用户凭证浏览器后显示空白页面,请修改系统的主机文件(linux中的/ etc/hosts和windows中的c:\ windows\system32\driver\etc\hosts)
在那里添加cas服务器ip
例如.
162.25.250.60 myapp 162.25.250.81 cas
任何疑问都可以澄清.
您可以参考以下内容:
https://wiki.jasig.org/display/CASUM/SSL+Troubleshooting+and+Reference+Guide
| 归档时间: |
|
| 查看次数: |
10867 次 |
| 最近记录: |