2015-02-13 28 views
7

Tôi đã tạo một dự án với SAML bảo mật mùa xuân.Bảo mật mùa xuân SAML + HTTPS đến một trang khác

tôi cần phải viết mã (tương tự dự án), kết nối với một máy chủ bằng HTTPS POST với SOAP:

PostMethod post = new PostMethod("https://www.somepage.com"); 
    post.setRequestHeader("SOAPAction", "action"); 
    post.setRequestEntity(new StringRequestEntity(soapXML, "text/xml", "UTF-8")); 

    HttpClient httpclient = new HttpClient(); 
    httpclient.executeMethod(post); 

    String responseString = post.getResponseBodyAsString(); 

Có một lỗi:

SSL ngang hàng không xác nhận hostname cho name: null

Và mọi yêu cầu HTTPS đều bị chặn bởi SAML bảo mật mùa xuân.

Cấu hình sử dụng để keystore cho nhà cung cấp SAML IDP, nhưng tôi cần phải gửi yêu cầu đến một máy chủ:

@Configuration 
@EnableWebMvcSecurity 
@EnableGlobalMethodSecurity(securedEnabled = true) 
@EnableAutoConfiguration(exclude = {org.springframework.boot.autoconfigure.security.SecurityAutoConfiguration.class, 
org.springframework.boot.actuate.autoconfigure.ManagementSecurityAutoConfiguration.class}) 
@Order(SecurityProperties.ACCESS_OVERRIDE_ORDER) 
public class WebSecurityConfig extends WebSecurityConfigurerAdapter { 

@Autowired 
private SAMLUserDetailsServiceImpl samlUserDetailsServiceImpl; 

// 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() throws MetadataProviderException { 
    SAMLContextProviderImpl sAMLContextProviderImpl = new SAMLContextProviderImpl(); 
    MetadataCredentialResolver metadataCredentialResolver = new MetadataCredentialResolver(metadata(), keyManager()); 
    metadataCredentialResolver.setUseXmlMetadata(false); 
    sAMLContextProviderImpl.setMetadataResolver(metadataCredentialResolver); 
    return 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() { 
    return new WebSSOProfileConsumerImpl(); 
} 

// 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() { 
    return new SingleLogoutProfileImpl(); 
} 

// Central storage of cryptographic keys 
@Bean 
public KeyManager keyManager() { 
    DefaultResourceLoader loader = new DefaultResourceLoader(); 
    Resource storeFile = loader 
    .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() { 
    return new 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(false); 
    extendedMetadata.setSignMetadata(true); 
    return extendedMetadata; 
} 

// IDP Discovery Service 
@Bean 
public SAMLDiscovery samlIDPDiscovery() { 
    SAMLDiscovery idpDiscovery = new SAMLDiscovery(); 
    idpDiscovery.setIdpSelectionPath("/saml/idpSelection"); 
    return idpDiscovery; 
} 

@Bean 
@Qualifier("idp-ssocircle") 
public ExtendedMetadataDelegate ssoCircleExtendedMetadataProvider() 
     throws MetadataProviderException { 
    @SuppressWarnings({"deprecation"}) 
    //HTTPMetadataProvider httpMetadataProvider 
    // = new HTTPMetadataProvider("https://idp.ssocircle.com/idp-meta.xml", 5000); 

    FilesystemMetadataProvider httpMetadataProvider = new FilesystemMetadataProvider(new File("FederationMetadata.xml")); 
    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(ssoCircleExtendedMetadataProvider()); 
    return new CachingMetadataManager(providers); 
} 

// Filter automatically generates default SP metadata 
@Bean 
public MetadataGenerator metadataGenerator() { 
    MetadataGenerator metadataGenerator = new MetadataGenerator(); 
    metadataGenerator.setEntityId("com:vdenotaris:spring: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 SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler() { 
    SavedRequestAwareAuthenticationSuccessHandler successRedirectHandler 
      = new SavedRequestAwareAuthenticationSuccessHandler(); 
    successRedirectHandler.setDefaultTargetUrl("/landing"); 
    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(authenticationManager()); 
    samlWebSSOHoKProcessingFilter.setAuthenticationFailureHandler(authenticationFailureHandler()); 
    return samlWebSSOHoKProcessingFilter; 
} 

// Processing filter for WebSSO profile messages 
@Bean 
public SAMLProcessingFilter samlWebSSOProcessingFilter() throws Exception { 
    SAMLProcessingFilter samlWebSSOProcessingFilter = new SAMLProcessingFilter(); 
    samlWebSSOProcessingFilter.setAuthenticationManager(authenticationManager()); 
    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); 
} 

/** 
* Returns the authentication manager currently used by Spring. It 
* represents a bean definition with the aim allow wiring from other classes 
* performing the Inversion of Control (IoC). 
* 
* @throws Exception 
*/ 
@Bean 
@Override 
public AuthenticationManager authenticationManagerBean() throws Exception { 
    return super.authenticationManagerBean(); 
} 

/** 
* Defines the web based security configuration. 
* 
* @param http It allows configuring web based security for specific http 
* requests. 
* @throws Exception 
*/ 
@Override 
protected void configure(HttpSecurity http) throws Exception { 
    http 
      .httpBasic() 
      .authenticationEntryPoint(samlEntryPoint()); 
    http 
      .csrf() 
      .disable(); 
    http 
      .addFilterBefore(metadataGeneratorFilter(), ChannelProcessingFilter.class) 
      .addFilterAfter(samlFilter(), BasicAuthenticationFilter.class); 
    http 
      .authorizeRequests() 
      .antMatchers("/").permitAll() 
      .antMatchers("/index.html").permitAll() 
      .antMatchers("/index").permitAll() 
      .antMatchers("/error").permitAll() 
      .antMatchers("/login").permitAll() 
      .antMatchers("/saml/**").permitAll() 
      .anyRequest().authenticated() 
      .and().formLogin().loginPage("/login").permitAll(); 

    http 
      .logout() 
      .logoutSuccessUrl("/"); 
} 

/** 
* Sets a custom authentication provider. 
* 
* @param auth SecurityBuilder used to create an AuthenticationManager. 
* @throws Exception 
*/ 
@Override 
protected void configure(AuthenticationManagerBuilder auth) throws Exception { 
    auth 
      .authenticationProvider(samlAuthenticationProvider()); 
} 

} 

Logs:

[ERROR] org.springframework.security.saml.trust.MetadataCredentialResolver - PKIX path construction failed for untrusted credential: [subjectName='CN=test.test.pl,OU=test,O=test,L=test,ST=test,C=PL,2.5.4.5=#1320487a772f77645a513079554c4c346c3246716c76616f64694f6f34643149676a']: unable to find valid certification path to requested target 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Trust of untrusted credential could not be established via PKIX validation 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Attempting PKIX validation of untrusted credential 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Beginning PKIX validation using trusted validation information 
[DEBUG] org.opensaml.xml.security.x509.BasicX509CredentialNameEvaluator - Supplied trusted names are null or empty, skipping name evaluation 
[ERROR] org.springframework.security.saml.trust.MetadataCredentialResolver - PKIX path construction failed for untrusted credential: [subjectName='CN=test.test.pl,OU=test,O=test,L=test,ST=test,C=PL,2.5.4.5=#1320487a772f77645a513079554c4c346c3246716c76616f64694f6f34643149676a']: unable to find valid certification path to requested target 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Trust of untrusted credential could not be established via PKIX validation 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Attempting PKIX validation of untrusted credential 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Beginning PKIX validation using trusted validation information 
[DEBUG] org.opensaml.xml.security.x509.BasicX509CredentialNameEvaluator - Supplied trusted names are null or empty, skipping name evaluation 
[ERROR] org.springframework.security.saml.trust.MetadataCredentialResolver - PKIX path construction failed for untrusted credential: [subjectName='CN=test.test.pl,OU=test,O=test,L=test,ST=test,C=PL,2.5.4.5=#1320487a772f77645a513079554c4c346c3246716c76616f64694f6f34643149676a']: unable to find valid certification path to requested target 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Trust of untrusted credential could not be established via PKIX validation 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Attempting PKIX validation of untrusted credential 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Beginning PKIX validation using trusted validation information 
[DEBUG] org.opensaml.xml.security.x509.BasicX509CredentialNameEvaluator - Supplied trusted names are null or empty, skipping name evaluation 
[ERROR] org.springframework.security.saml.trust.MetadataCredentialResolver - PKIX path construction failed for untrusted credential: [subjectName='test,O=test,L=test,ST=test,C=PL,2.5.4.5=#1320487a772f77645a513079554c4c346c3246716c76616f64694f6f34643149676a']: unable to find valid certification path to requested target 
[DEBUG] org.opensaml.xml.security.x509.PKIXX509CredentialTrustEngine - Trust of untrusted credential could not be established via PKIX validation 
+0

Bạn đang sử dụng bean "org.springframework.security.saml.trust.httpclient.TLSProtocolConfigurer"? –

+0

Vui lòng đính kèm cấu hình mùa xuân và nhật ký hoàn chỉnh của bạn. –

Trả lời

7

Bạn đang sử dụng đậu TLSProtocolConfigurer mà thay đổi giấy chứng nhận đáng tin cậy và hostname xác minh giao thức HTTPS trong HTTP Client. Bạn có thể hoàn nguyên hành vi của HTTP Client trở về mặc định bằng cách loại bỏ bean này. Sau đó, bạn sẽ cần phải đảm bảo rằng chứng chỉ được sử dụng bởi các thực thể mà bạn tải siêu dữ liệu (https://idp.ssocircle.com/idp-meta.xml) được tin cậy trong cacerts của bạn hoặc sử dụng điểm cuối không có https (http://idp.ssocircle.com/idp-meta.xml).

Hoặc, bạn có thể tắt xác minh tên máy chủ bằng cách đặt thuộc tính sslHostnameVerification thành allowAll trên bean TLSProtocolConfigurer. Bạn cũng sẽ cần phải đảm bảo rằng giấy chứng nhận HTTPS của https://www.somepage.com (hoặc CA của nó) được bao gồm trong samlKeystore.jks (xem Spring SAML manual).

Bạn có thể tìm thêm chi tiết về hạt TLSProtocolConfigurer trong Spring SAML manual, chapter HTTP-based metadata provider with SSL.

Các vấn đề liên quan