gpt4 book ai didi

java - Spring Security SAML + HTTPS 到另一个页面

转载 作者:塔克拉玛干 更新时间:2023-11-03 04:20:13 26 4
gpt4 key购买 nike

我使用 Spring Security SAML 创建了一个项目。

我需要编写一个代码(同一个项目),它通过带有 SOAP 的 HTTPS POST 连接到另一台服务器:

    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();

出现错误:

SSL 对等端未能通过名称的主机名验证:null

并且每个 HTTPS 请求都被 Spring Security SAML 阻止。

配置用于 SAML Idp 提供商的 keystore ,但我需要将请求发送到另一台服务器:

@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());
}

}

日志:

[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

最佳答案

您正在使用 bean TLSProtocolConfigurer,它会更改 HTTP 客户端中 HTTPS 协议(protocol)的可信证书和主机名验证。您可以通过删除此 bean 将 HTTP 客户端的行为恢复为默认值。然后,您需要确保从中加载元数据 (https://idp.ssocircle.com/idp-meta.xml) 的实体使用的证书在您的 cacerts 中是可信的,或者使用不带 https 的端点 (http://idp.ssocircle.com/idp-meta.xml)。

或者,您可以通过将 bean TLSProtocolConfigurer 上的属性 sslHostnameVerification 设置为 allowAll 来禁用主机名验证。您还需要确保 https://www.somepage.com 的 HTTPS 证书(或其 CA)包含在 samlKeystore.jks 中(参见 Spring SAML manual)。

您可以在 Spring SAML manual, chapter HTTP-based metadata provider with SSL 中找到有关 TLSProtocolConfigurer bean 的更多详细信息.

关于java - Spring Security SAML + HTTPS 到另一个页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28505824/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com