Spring boot 在Spring SAML中SSL对等主机名验证失败

Spring boot 在Spring SAML中SSL对等主机名验证失败,spring-boot,spring-saml,Spring Boot,Spring Saml,我正试图将我的Spring Boot项目配置为对第三方IDP使用SAML身份验证。我已经通过SSOCIRCE提供程序实现了配置,现在我想将其切换到其他提供程序 SAML元数据端点支持HTTPS,我已经创建了一个密钥库,其中包含元数据中提供的证书(用于签名和加密)和HTTP端点提供的证书(基于)。然后,我将它们保存在证书文件($CERTIFICATE_file)中,并使用此脚本生成密钥库: keytool -delete -alias third-party -keystore $KEYSTORE

我正试图将我的Spring Boot项目配置为对第三方IDP使用SAML身份验证。我已经通过SSOCIRCE提供程序实现了配置,现在我想将其切换到其他提供程序

SAML元数据端点支持HTTPS,我已经创建了一个密钥库,其中包含元数据中提供的证书(用于签名和加密)和HTTP端点提供的证书(基于)。然后,我将它们保存在证书文件($CERTIFICATE_file)中,并使用此脚本生成密钥库:

keytool -delete -alias third-party -keystore $KEYSTORE_FILE -storepass $KEYSTORE_PASSWORD
keytool -import -alias third-party -file $CERTIFICATE_FILE -keystore $KEYSTORE_FILE -storepass $KEYSTORE_PASSWORD -noprompt
keytool -genkeypair -alias mycompany -keypass mycompanypass -keystore $KEYSTORE_FILE
然后,当使用此密钥库检索SAML元数据时,出现以下错误:

org.opensaml.saml2.metadata.provider.MetadataProviderException: org.opensaml.saml2.metadata.provider.MetadataProviderException: Error retrieving metadata from https://third.party.provider/metadata
    at org.opensaml.saml2.metadata.provider.HTTPMetadataProvider.fetchMetadata(HTTPMetadataProvider.java:274)
    at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.refresh(AbstractReloadingMetadataProvider.java:267)
    at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.doInitialization(AbstractReloadingMetadataProvider.java:236)
    at org.opensaml.saml2.metadata.provider.AbstractMetadataProvider.initialize(AbstractMetadataProvider.java:407)
    at org.springframework.security.saml.metadata.ExtendedMetadataDelegate.initialize(ExtendedMetadataDelegate.java:167)
    at org.springframework.security.saml.metadata.MetadataManager.initializeProvider(MetadataManager.java:412)
    at org.springframework.security.saml.metadata.MetadataManager.refreshMetadata(MetadataManager.java:238)
    at org.springframework.security.saml.metadata.CachingMetadataManager.refreshMetadata(CachingMetadataManager.java:86)
    at org.springframework.security.saml.metadata.MetadataManager$RefreshTask.run(MetadataManager.java:1040)
    at java.util.TimerThread.mainLoop(Timer.java:555)
    at java.util.TimerThread.run(Timer.java:505)
Caused by: org.opensaml.saml2.metadata.provider.MetadataProviderException: Error retrieving metadata from https://third.party.provider/metadata
    at org.opensaml.saml2.metadata.provider.HTTPMetadataProvider.fetchMetadata(HTTPMetadataProvider.java:274)
    at org.opensaml.saml2.metadata.provider.AbstractReloadingMetadataProvider.refresh(AbstractReloadingMetadataProvider.java:255)
    ... 9 common frames omitted
Caused by: javax.net.ssl.SSLPeerUnverifiedException: SSL peer failed hostname validation for name: null
    at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.verifyHostname(TLSProtocolSocketFactory.java:233)
    at org.opensaml.ws.soap.client.http.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:186)
    at org.springframework.security.saml.trust.httpclient.TLSProtocolSocketFactory.createSocket(TLSProtocolSocketFactory.java:97)
    at org.apache.commons.httpclient.HttpConnection.open(HttpConnection.java:707)
    at org.apache.commons.httpclient.MultiThreadedHttpConnectionManager$HttpConnectionAdapter.open(MultiThreadedHttpConnectionManager.java:1361)
    at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:387)
    at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:171)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:397)
    at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:323)
    at org.opensaml.saml2.metadata.provider.HTTPMetadataProvider.fetchMetadata(HTTPMetadataProvider.java:250)
    ... 10 common frames omitted
这些是我在vdenotaris链接项目中配置的相关部分:

//设置TLS套接字工厂
@豆子
公共TLSProtocolConfigurer TLSProtocolConfigurer(){
返回新的TLSProtocolConfigurer();
}
@豆子
公共协议socketFactory socketFactory(){
返回新的TLSProtocolSocketFactory(keyManager(),null,“allowAll”);
}
@豆子
公共协议socketFactoryProtocol(){
返回新协议(“https”,socketFactory(),443);
}
@豆子
调用FactoryBean socketFactoryInitialization()的公共方法{
MethodInvokingFactoryBean MethodInvokingFactoryBean=新方法InvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(Protocol.class);
方法调用FactoryBean.setTargetMethod(“registerProtocol”);
对象[]args={“https”,socketFactoryProtocol()};
methodInvokingFactoryBean.setArguments(args);
返回方法调用FactoryBean;
}
//加密密钥的中央存储
@豆子
公钥管理器密钥管理器(){
DefaultResourceLoader=新的DefaultResourceLoader();
Resource storeFile=loader.getResource(“classpath:/saml/mysamlkystore.jks”);
字符串storePass=“storePass”;
Map passwords=new HashMap();
密码。输入(“mycompany”、“mycompanypass”);
字符串defaultKey=“mycompany”;
返回新的JKSKeyManager(storeFile、storePass、密码、defaultKey);
}
然而,在这里我发现了一些误解。据我所知,
TLSProtocolConfigurer
本身创建了一个
TLSProtocolSocketFactory
,那么为什么示例项目会同时创建这两个bean呢?根据说明,使用
TLSProtocolConfigurer
应该足够了,但是如何创建
socketFactoryProtocol()


如果这里有一些提示,我将不胜感激。

我没有提供导入的证书文件的密码:

@Bean
公钥管理器密钥管理器(){
DefaultResourceLoader=新的DefaultResourceLoader();
Resource storeFile=loader.getResource(“classpath:/saml/mysamlkystore.jks”);
字符串storePass=“storePass”;
Map passwords=new HashMap();
密码。输入(“mycompany”、“mycompanypass”);
密码。put(“第三方”、“mycompanypass”);
字符串defaultKey=“mycompany”;
返回新的JKSKeyManager(storeFile、storePass、密码、defaultKey);
}
这样,应用程序就可以从密钥库读取证书并信任它们,而无需将它们安装在JDK cacerts中

@Bean
    @Qualifier("idp-ssocircle")
    public ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider()
        throws MetadataProviderException {
    String idpSSOCircleMetadataURL = "https://idp.ssocircle.com/idp-meta.xml";
    HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider(
            this.backgroundTaskTimer, httpClient(), idpSSOCircleMetadataURL);
    httpMetadataProvider.setParserPool(parserPool());
    ExtendedMetadataDelegate extendedMetadataDelegate = 
            new ExtendedMetadataDelegate(httpMetadataProvider, extendedMetadata());
    extendedMetadataDelegate.setMetadataTrustCheck(false);
    extendedMetadataDelegate.setMetadataRequireSignature(false);
    backgroundTaskTimer.purge();
    return extendedMetadataDelegate;
}

extendedMetadataDelegate.setMetadataTrustCheck(false)

这是我的JKS密钥管理器bean配置

@Bean
public ProtocolSocketFactory socketFactory() {
return new TLSProtocolSocketFactory(keyManager(), null, "default");
}

@Bean
public KeyManager keyManager() {
DefaultResourceLoader loader = new DefaultResourceLoader();
Resource storeFile = loader.getResource("classpath:/saml/samlKeystore.jks");
String storePass = keyStorePwd;
Map<String, String> passwords = new HashMap<String, String>();
passwords.put(keyStoreAlias, keyStorePwd);
String defaultKey = keyStoreAlias;
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);

}

只需删除
TLSProtocolConfigurer
bean并将元数据信任检查设置为
false

我也面临同样的问题。请帮我做这件事。我已经创建了新的证书和密钥库,但同样的错误是相同的。SSL对等方未能验证名称的主机名:null@user3029929请发布一个包含所有细节的问题。我有同样的问题(同样的错误),这是在帖子中提到的@Xtreme Biker:正如你在回答中提到的,你刚刚为证书添加了密码,它对你有效。在我的案例中,我创建了没有密码的新证书,我得到了与此问题中提到的相同的错误。可能是我正在以一种工作方式创建证书。你能告诉我正确的方法吗。。
openssl s_client -showcerts -connect iam-sso.google.net:443 </dev/null 2>/dev/null|openssl x509 -outform PEM >mycertfile.pem
keytool -import -alias "new-public-cert" -keystore /usr/share/tomcat8/webapps/ROOT/WEB-INF/classes/saml/samlKeystore.jks