gpt4 book ai didi

java - Spring Security SAML - 如何配置客户端身份验证?

转载 作者:行者123 更新时间:2023-12-01 10:31:52 24 4
gpt4 key购买 nike

我正在尝试调整 Spring Security SAML sample application使用测试 IDP(由其他人提供给我)而不是 ssocircle。单击“SAML 登录”正确地将我重定向到 IDP 的 SSO 登录页面,但在登录并重定向回示例应用程序后,我收到一个异常(显然是在工件解析期间),其根源是:

org.opensaml.ws.message.decoder.MessageDecodingException: Error when sending request to artifact resolution service.
at org.springframework.security.saml.websso.ArtifactResolutionProfileImpl.getArtifactResponse(ArtifactResolutionProfileImpl.java:110)
at org.springframework.security.saml.websso.ArtifactResolutionProfileBase.resolveArtifact(ArtifactResolutionProfileBase.java:101)
... 34 more
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.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:346)
at org.springframework.security.saml.websso.ArtifactResolutionProfileImpl.getArtifactResponse(ArtifactResolutionProfileImpl.java:99)

经过一段时间的挖掘,我意识到服务器期望在相关端口进行客户端身份验证。如果我像这样连接到它,我会得到有效的响应:

curl -k --cert spcert.pem --key spkey.pem https://testidp:8110/idp/profile/SAML2/SOAP/ArtifactResolution

此外,如果我通过编辑 IDP tomcat 的 server.xml 并将相关 <Connector> 中的 clientAuth 更改为“false”来禁用 IDP 上的 clientAuth,则异常就会消失。标签。

如果我像这样使用 apache httpclient,连接到 IDP 的端口 8110 工作正常

package at.awst.perkele.httpstest;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;

import javax.net.ssl.SSLContext;

import org.apache.http.HttpEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.conn.ssl.TrustSelfSignedStrategy;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

public class HTTPSTest {
private static final String CA_KEYSTORE_TYPE = KeyStore.getDefaultType(); // "JKS";
private static final String CA_KEYSTORE_PATH = "myKeystore.jks";
private static final String CA_KEYSTORE_PASS = "secret";

private static final String CLIENT_KEYSTORE_TYPE = KeyStore.getDefaultType(); // "JKS";
private static final String CLIENT_KEYSTORE_PATH = "myKeystore.jks";
private static final String CLIENT_KEYSTORE_PASS = "secret";

private static final String HTTPS_URL = "https://testidp:8110/idp/profile/SAML2/SOAP/ArtifactResolution";

public static void main(String[] args) throws Exception {
SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(createSslCustomContext(), new String[] { "TLSv1" },
null, SSLConnectionSocketFactory.getDefaultHostnameVerifier());

try (CloseableHttpClient httpclient = HttpClients.custom().setSSLSocketFactory(csf).build()) {
HttpGet req = new HttpGet(HTTPS_URL);
try (CloseableHttpResponse response = httpclient.execute(req)) {
HttpEntity entity = response.getEntity();

System.out.println(String.format("Reponse status: %s", response.getStatusLine()));
System.out.println(String.format("Response entity: %s", entity.toString()));

BufferedReader in = new BufferedReader(new InputStreamReader(entity.getContent()));
String line = null;
while ((line = in.readLine()) != null) {
System.out.println(line);
}
EntityUtils.consume(entity);
}
}
}

private static SSLContext createSslCustomContext() throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException, KeyManagementException, UnrecoverableKeyException {
// Trusted CA keystore
KeyStore tks = KeyStore.getInstance(CA_KEYSTORE_TYPE);
tks.load(new FileInputStream(CA_KEYSTORE_PATH), CA_KEYSTORE_PASS.toCharArray());

// Client keystore
KeyStore cks = KeyStore.getInstance(CLIENT_KEYSTORE_TYPE);
cks.load(new FileInputStream(CLIENT_KEYSTORE_PATH), CLIENT_KEYSTORE_PASS.toCharArray());

SSLContext sslcontext = SSLContexts.custom().loadTrustMaterial(tks, new TrustSelfSignedStrategy())
.loadKeyMaterial(cks, CLIENT_KEYSTORE_PASS.toCharArray())
.build();
return sslcontext;
}

}

但是,我不知道如何正确配置 Spring SAML 的 TLSProtocolConfigurer(或使用客户端 key 所需的任何内容)。

那么,我如何告诉 Spring Security SAML 在 TLS/SSL 连接中使用我的客户端 key 进行客户端身份验证?

最佳答案

好的,弄清楚如何在 Spring SAML 的 TLS 连接中启用 clientAuth。这是我的 securityContext.xml 中的服务提供商配置:

<bean class="org.springframework.security.saml.metadata.ExtendedMetadataDelegate">
<constructor-arg>
<bean class="org.opensaml.saml2.metadata.provider.FilesystemMetadataProvider">
<constructor-arg>
<value type="java.io.File">classpath:metadata/sp.xml</value>
</constructor-arg>
<property name="parserPool" ref="parserPool" />
</bean>
</constructor-arg>
<constructor-arg>
<bean class="org.springframework.security.saml.metadata.ExtendedMetadata">
<property name="local" value="true" />
<property name="signMetadata" value="true" />
<property name="signingKey" value="mykey" />
<property name="encryptionKey" value="mykey" />
<property name="tlsKey" value="mykey" />
</bean>
</constructor-arg>
</bean>

通过 <property name="tlsKey" value="mykey" /> 设置客户端 key 来启用 ClientAuth

key 必须像往常一样在 JKSKeyManager 中声明:

<bean id="keyManager" class="org.springframework.security.saml.key.JKSKeyManager">
<constructor-arg value="classpath:security/keystore.jks" />
<constructor-arg type="java.lang.String" value="secret" />
<constructor-arg>
<map>
<entry key="mykey" value="secret" />
</map>
</constructor-arg>
<constructor-arg type="java.lang.String" value="mykey" />
</bean>

这是mentioned in the docs here作为“填充用于 SSL/TLS 客户端身份验证的凭据。如果 ExtendedMetadata 指定属性 tlsKey,它将用作从 keyManager bean 查找 key 的别名。否则将不会为客户端身份验证提供任何凭据。”我花了一段时间才发现;-)

关于java - Spring Security SAML - 如何配置客户端身份验证?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35045669/

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