我们将Salesforce设置为IDP,我们的应用程序是SP,使用Spring SAML扩展。但是我们得到错误' SSL对等失败主机名验证名称:null'
2016-02-24 11:51:18 [localhost-startStop-1 ] ERROR o.s.s.s.t.MetadataCredentialResolver : 111 - PKIX path construction failed for untrusted credential: [subjectName='CN=*.my.salesforce.com,OU=Applications,O=Salesforce.com\, Inc,L=San Francisco,ST=California,C=US']: unable to find valid certification path to requested target
2016-02-24 11:51:18 [localhost-startStop-1 ] INFO o.a.c.h.HttpMethodDirector : 439 - I/O exception (javax.net.ssl.SSLPeerUnverifiedException) caught when processing request: SSL peer failed hostname validation for name: null
2016-02-24 11:51:18 [localhost-startStop-1 ] INFO o.a.c.h.HttpMethodDirector : 445 - Retrying request
2016-02-24 11:51:18 [localhost-startStop-1 ] ERROR o.s.s.s.t.MetadataCredentialResolver : 111 - PKIX path construction failed for untrusted credential: [subjectName='CN=*.my.salesforce.com,OU=Applications,O=Salesforce.com\, Inc,L=San Francisco,ST=California,C=US']: unable to find valid certification path to requested target
2016-02-24 11:51:18 [localhost-startStop-1 ] INFO o.a.c.h.HttpMethodDirector : 439 - I/O exception (javax.net.ssl.SSLPeerUnverifiedException) caught when processing request: SSL peer failed hostname validation for name: null
2016-02-24 11:51:18 [localhost-startStop-1 ] INFO o.a.c.h.HttpMethodDirector : 445 - Retrying request
2016-02-24 11:51:19 [localhost-startStop-1 ] ERROR o.s.s.s.t.MetadataCredentialResolver : 111 - PKIX path construction failed for untrusted credential: [subjectName='CN=*.my.salesforce.com,OU=Applications,O=Salesforce.com\, Inc,L=San Francisco,ST=California,C=US']: unable to find valid certification path to requested target
2016-02-24 11:51:19 [localhost-startStop-1 ] INFO o.a.c.h.HttpMethodDirector : 439 - I/O exception (javax.net.ssl.SSLPeerUnverifiedException) caught when processing request: SSL peer failed hostname validation for name: null
2016-02-24 11:51:19 [localhost-startStop-1 ] INFO o.a.c.h.HttpMethodDirector : 445 - Retrying request
2016-02-24 11:51:19 [localhost-startStop-1 ] ERROR o.s.s.s.t.MetadataCredentialResolver : 111 - PKIX path construction failed for untrusted credential: [subjectName='CN=*.my.salesforce.com,OU=Applications,O=Salesforce.com\, Inc,L=San Francisco,ST=California,C=US']: unable to find valid certification path to requested target
2016-02-24 11:51:19 [localhost-startStop-1 ] ERROR o.o.s.m.p.HTTPMetadataProvider : 273 - Error retrieving metadata from https://flexsaml-dev-ed.my.salesforce.com/.well-known/samlidp/RevitasCCSpring.xml
javax.net.ssl.SSLPeerUnverifiedException: SSL peer failed hostname validation for name: null
这是我们的SAML配置类。
@Autowired
private SAMLUserDetailsServiceImpl samlUserDetailsServiceImpl;
@Autowired
private ResourceLoader resourceLoader;
@Autowired
private Environment env;
@Autowired
private AuthenticationUtilService authenticationUtilService;
// Initialization of the velocity engine
@Bean
public VelocityEngine velocityEngine() {
return VelocityFactory.getEngine();
}
// XML parser pool needed for OpenSAML parsing
@Bean(initMethod = "initialize")
public StaticBasicParserPool parserPool() {
return new StaticBasicParserPool();
}
@Bean(name = "parserPoolHolder")
public ParserPoolHolder parserPoolHolder() {
return new ParserPoolHolder();
}
// Bindings, encoders and decoders used for creating and parsing messages
@Bean
public MultiThreadedHttpConnectionManager multiThreadedHttpConnectionManager() {
return new MultiThreadedHttpConnectionManager();
}
@Bean
public HttpClient httpClient() {
return new HttpClient(multiThreadedHttpConnectionManager());
}
// SAML Authentication Provider responsible for validating of received SAML
// messages
@Bean
public SAMLAuthenticationProvider samlAuthenticationProvider() {
SAMLAuthenticationProvider samlAuthenticationProvider = new SAMLAuthenticationProvider();
samlAuthenticationProvider.setUserDetails(samlUserDetailsServiceImpl);
samlAuthenticationProvider.setForcePrincipalAsString(false);
return samlAuthenticationProvider;
}
// Provider of default SAML Context
@Bean
public SAMLContextProviderImpl contextProvider() {
return new SAMLContextProviderImpl();
}
// Initialization of OpenSAML library
@Bean
public static SAMLBootstrap sAMLBootstrap() {
return new SAMLBootstrap();
}
// Logger for SAML messages and events
@Bean
public SAMLDefaultLogger samlLogger() {
return new SAMLDefaultLogger();
}
// SAML 2.0 WebSSO Assertion Consumer
@Bean
public WebSSOProfileConsumer webSSOprofileConsumer() {
WebSSOProfileConsumerImpl webSSOProfileConsumer = new WebSSOProfileConsumerImpl();
webSSOProfileConsumer.setResponseSkew(6000000);
return webSSOProfileConsumer;
}
// SAML 2.0 Holder-of-Key WebSSO Assertion Consumer
@Bean
public WebSSOProfileConsumerHoKImpl hokWebSSOprofileConsumer() {
return new WebSSOProfileConsumerHoKImpl();
}
// SAML 2.0 Web SSO profile
@Bean
public WebSSOProfile webSSOprofile() {
return new WebSSOProfileImpl();
}
// SAML 2.0 Holder-of-Key Web SSO profile
@Bean
public WebSSOProfileConsumerHoKImpl hokWebSSOProfile() {
return new WebSSOProfileConsumerHoKImpl();
}
// SAML 2.0 ECP profile
@Bean
public WebSSOProfileECPImpl ecpprofile() {
return new WebSSOProfileECPImpl();
}
@Bean
public SingleLogoutProfile logoutprofile() {
SingleLogoutProfileImpl singleLogoutProfile = new SingleLogoutProfileImpl();
singleLogoutProfile.setResponseSkew(6000000);
return singleLogoutProfile;
}
// Central storage of cryptographic keys
@Bean
public KeyManager keyManager() {
Resource storeFile = null;
if (StringUtils.isEmpty(env.getProperty("saml.keystore.file"))) {
storeFile = resourceLoader
.getResource("file:" + env.getProperty("saml.keystore.file"));
} else {
storeFile = resourceLoader.getResource("classpath:/saml/samlKeystore.jks");
}
String storePass = "nalle123";
Map<String, String> passwords = new HashMap<String, String>();
passwords.put("apollo", "nalle123");
String defaultKey = "apollo";
return new JKSKeyManager(storeFile, storePass, passwords, defaultKey);
}
// Setup TLS Socket Factory
@Bean
public TLSProtocolConfigurer tlsProtocolConfigurer() {
TLSProtocolConfigurer tlsProtocolConfigurer = new TLSProtocolConfigurer();
tlsProtocolConfigurer.setSslHostnameVerification("allowAll");
return tlsProtocolConfigurer;
}
@Bean
public ProtocolSocketFactory socketFactory() {
return new TLSProtocolSocketFactory(keyManager(), null, "default");
}
@Bean
public Protocol socketFactoryProtocol() {
return new Protocol("https", socketFactory(), 443);
}
@Bean
public MethodInvokingFactoryBean socketFactoryInitialization() {
MethodInvokingFactoryBean methodInvokingFactoryBean = new MethodInvokingFactoryBean();
methodInvokingFactoryBean.setTargetClass(Protocol.class);
methodInvokingFactoryBean.setTargetMethod("registerProtocol");
Object[] args = {"https", socketFactoryProtocol()};
methodInvokingFactoryBean.setArguments(args);
return methodInvokingFactoryBean;
}
@Bean
public WebSSOProfileOptions defaultWebSSOProfileOptions() {
WebSSOProfileOptions webSSOProfileOptions = new WebSSOProfileOptions();
webSSOProfileOptions.setIncludeScoping(false);
return webSSOProfileOptions;
}
// Entry point to initialize authentication, default values taken from
// properties file
@Bean
public SAMLEntryPoint samlEntryPoint() {
SAMLEntryPoint samlEntryPoint = new SAMLEntryPoint();
samlEntryPoint.setDefaultProfileOptions(defaultWebSSOProfileOptions());
return samlEntryPoint;
}
// Setup advanced info about metadata
@Bean
public ExtendedMetadata extendedMetadata() {
ExtendedMetadata extendedMetadata = new ExtendedMetadata();
extendedMetadata.setIdpDiscoveryEnabled(true);
extendedMetadata.setSignMetadata(false);
return extendedMetadata;
}
// IDP Discovery Service
@Bean
public SAMLDiscovery samlIDPDiscovery() {
SAMLDiscovery idpDiscovery = new SAMLDiscovery();
idpDiscovery.setIdpSelectionPath("/saml/idpSelection");
return idpDiscovery;
}
@Bean
@Qualifier("idp-local")
public ExtendedMetadataDelegate localIdpExtendedMetadataProvider()
throws MetadataProviderException {
File file = null;
try {
file = resourceLoader.getResource("classpath:/saml/metadata/idp.xml").getFile();
} catch (IOException e) {
theLogger.error("File doesn't exist...");
return null;
}
Timer backgroundTaskTimer = new Timer(true);
FilesystemMetadataProvider filesystemMetadataProvider = new FilesystemMetadataProvider(
backgroundTaskTimer, file);
filesystemMetadataProvider.setParserPool(parserPool());
ExtendedMetadataDelegate extendedMetadataDelegate =
new ExtendedMetadataDelegate(filesystemMetadataProvider, extendedMetadata());
extendedMetadataDelegate.setMetadataTrustCheck(true);
extendedMetadataDelegate.setMetadataRequireSignature(false);
return extendedMetadataDelegate;
}
@Bean
@Qualifier("idp-sfdcHttp")
public ExtendedMetadataDelegate sfdcHttpExtendedMetadataProvider()
throws MetadataProviderException {
String sfdcMetadaURL = "https://flexsaml-dev-ed.my.salesforce.com/.well-known/samlidp/RevitasCCSpring.xml";
Timer backgroundTaskTimer = new Timer(true);
HTTPMetadataProvider httpMetadataProvider = new HTTPMetadataProvider(
backgroundTaskTimer, httpClient(), sfdcMetadaURL);
httpMetadataProvider.setParserPool(parserPool());
ExtendedMetadataDelegate extendedMetadataDelegate =
new ExtendedMetadataDelegate(httpMetadataProvider, extendedMetadata());
extendedMetadataDelegate.setMetadataTrustCheck(false);
extendedMetadataDelegate.setMetadataRequireSignature(false);
return extendedMetadataDelegate;
}
// IDP Metadata configuration - paths to metadata of IDPs in circle of trust
// is here
// Do no forget to call iniitalize method on providers
@Bean
@Qualifier("metadata")
public CachingMetadataManager metadata() throws MetadataProviderException {
List<MetadataProvider> providers = new ArrayList<MetadataProvider>();
providers.add(localIdpExtendedMetadataProvider());
providers.add(sfdcHttpExtendedMetadataProvider());
return new CachingMetadataManager(providers);
}
// Filter automatically generates default SP metadata
@Bean
public MetadataGenerator metadataGenerator() {
MetadataGenerator metadataGenerator = new MetadataGenerator();
metadataGenerator.setEntityId("com:revitas:saml:sp");
metadataGenerator.setExtendedMetadata(extendedMetadata());
metadataGenerator.setIncludeDiscoveryExtension(false);
metadataGenerator.setKeyManager(keyManager());
return metadataGenerator;
}
// The filter is waiting for connections on URL suffixed with filterSuffix
// and presents SP metadata there
@Bean
public MetadataDisplayFilter metadataDisplayFilter() {
return new MetadataDisplayFilter();
}
// Handler deciding where to redirect user after successful login
@Bean
public SAMLSuccessRedirectHandler successRedirectHandler() {
SAMLSuccessRedirectHandler successRedirectHandler =
new SAMLSuccessRedirectHandler();
return successRedirectHandler;
}
// Handler deciding where to redirect user after failed login
@Bean
public SimpleUrlAuthenticationFailureHandler authenticationFailureHandler() {
SimpleUrlAuthenticationFailureHandler failureHandler =
new SimpleUrlAuthenticationFailureHandler();
failureHandler.setUseForward(true);
failureHandler.setDefaultFailureUrl("/error");
return failureHandler;
}
@Bean
public SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter() throws Exception {
SAMLWebSSOHoKProcessingFilter samlWebSSOHoKProcessingFilter = new SAMLWebSSOHoKProcessingFilter();
samlWebSSOHoKProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
samlWebSSOHoKProcessingFilter.setAuthenticationManager(authenticationUtilService.getAuthenticationManager());
samlWebSSOHoKProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
return samlWebSSOHoKProcessingFilter;
}
// Processing filter for WebSSO profile messages
@Bean
public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception {
SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter();
samlWebSSOProcessingFilter.setAuthenticationManager(authenticationUtilService.getAuthenticationManager());
samlWebSSOProcessingFilter.setAuthenticationSuccessHandler(successRedirectHandler());
samlWebSSOProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler());
return samlWebSSOProcessingFilter;
}
@Bean
public MetadataGeneratorFilter metadataGeneratorFilter() {
return new MetadataGeneratorFilter(metadataGenerator());
}
// Handler for successful logout
@Bean
public SimpleUrlLogoutSuccessHandler successLogoutHandler() {
SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler();
successLogoutHandler.setDefaultTargetUrl("/");
return successLogoutHandler;
}
// Logout handler terminating local session
@Bean
public SecurityContextLogoutHandler logoutHandler() {
SecurityContextLogoutHandler logoutHandler =
new SecurityContextLogoutHandler();
logoutHandler.setInvalidateHttpSession(true);
logoutHandler.setClearAuthentication(true);
return logoutHandler;
}
// Filter processing incoming logout messages
// First argument determines URL user will be redirected to after successful
// global logout
@Bean
public SAMLLogoutProcessingFilter samlLogoutProcessingFilter() {
return new SAMLLogoutProcessingFilter(successLogoutHandler(),
logoutHandler());
}
// Overrides default logout processing filter with the one processing SAML
// messages
@Bean
public SAMLLogoutFilter samlLogoutFilter() {
return new SAMLLogoutFilter(successLogoutHandler(),
new LogoutHandler[]{logoutHandler()},
new LogoutHandler[]{logoutHandler()});
}
// Bindings
private ArtifactResolutionProfile artifactResolutionProfile() {
final ArtifactResolutionProfileImpl artifactResolutionProfile =
new ArtifactResolutionProfileImpl(httpClient());
artifactResolutionProfile.setProcessor(new SAMLProcessorImpl(soapBinding()));
return artifactResolutionProfile;
}
@Bean
public HTTPArtifactBinding artifactBinding(ParserPool parserPool, VelocityEngine velocityEngine) {
return new HTTPArtifactBinding(parserPool, velocityEngine, artifactResolutionProfile());
}
@Bean
public HTTPSOAP11Binding soapBinding() {
return new HTTPSOAP11Binding(parserPool());
}
@Bean
public HTTPPostBinding httpPostBinding() {
return new HTTPPostBinding(parserPool(), velocityEngine());
}
@Bean
public HTTPRedirectDeflateBinding httpRedirectDeflateBinding() {
return new HTTPRedirectDeflateBinding(parserPool());
}
@Bean
public HTTPSOAP11Binding httpSOAP11Binding() {
return new HTTPSOAP11Binding(parserPool());
}
@Bean
public HTTPPAOS11Binding httpPAOS11Binding() {
return new HTTPPAOS11Binding(parserPool());
}
// Processor
@Bean
public SAMLProcessorImpl processor() {
Collection<SAMLBinding> bindings = new ArrayList<SAMLBinding>();
bindings.add(httpRedirectDeflateBinding());
bindings.add(httpPostBinding());
bindings.add(artifactBinding(parserPool(), velocityEngine()));
bindings.add(httpSOAP11Binding());
bindings.add(httpPAOS11Binding());
return new SAMLProcessorImpl(bindings);
}
/**
* Define the security filter chain in order to support SSO Auth by using SAML 2.0
*
* @return Filter chain proxy
* @throws Exception
*/
@Bean
public FilterChainProxy samlFilter() throws Exception {
List<SecurityFilterChain> chains = new ArrayList<SecurityFilterChain>();
chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/login/**"),
samlEntryPoint()));
chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/logout/**"),
samlLogoutFilter()));
chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/metadata/**"),
metadataDisplayFilter()));
chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSO/**"),
samlWebSSOProcessingFilter()));
chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SSOHoK/**"),
samlWebSSOHoKProcessingFilter()));
chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/SingleLogout/**"),
samlLogoutProcessingFilter()));
chains.add(new DefaultSecurityFilterChain(new AntPathRequestMatcher("/saml/discovery/**"),
samlIDPDiscovery()));
return new FilterChainProxy(chains);
}
我们尝试了来自链接&#39; Spring Security SAML + HTTPS to another page&#39;的建议,其中1)禁用主机名验证或2)注释掉Bean&#39; TLSProtocolConfigurer&#39;并将Salesforce证书导入JDK cacerts,但它们都不起作用并得到相同的错误消息。
我们可以尝试哪些方法?
答案 0 :(得分:1)
1)将MetadataTrustCheck设置为false(extendedMetadataDelegate.setMetadataTrustCheck(false);每次添加IdP的元数据(在这种情况下未验证IdP签名)和
2)删除tlsProtocolConfigurer Bean
应解决您的问题。