java申请中的X509客户端证书

发布于 2025-02-08 19:30:39 字数 1983 浏览 1 评论 0原文

我知道我绕着爪哇的方式,但是在SSL证书的主题方面,我的经验不足。因此,我的整个方法可能是完整的和完全胡说八道的。

我要实现的目标是:我在Spring Boot应用程序中使用Apache CXF有一个Web服务构建。该WebService称为X509客户端证书,我想使用该证书从我已经配置的KeyCloak实例中获取JWT。当我这样做时,从KeyCloak获得令牌工作起作用:

var keystore = KeyStore.getInstance("PKCS12");
keystore.load(new ClassPathResource("keystore.pfx").getInputStream(), "myPassphrase".toCharArray());
HttpClient client = HttpClients.custom().setSSLContext(new SSLContextBuilder()
    .loadTrustMaterial(new ClassPathResource("truststore.jks").getFile(), "trustStorePW".toCharArray())
        .loadKeyMaterial(keystore, "myPassphrase".toCharArray())
        .build()
    ).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();

var postRequest = new HttpPost("https://localhost:8443/realms/master/protocol/openid-connect/token");
postRequest.addHeader("Content-Type", "application/x-www-form-urlencoded");
var entity = new StringEntity("grant_type=password&client_id=my-client&client_secret=my-secret");
postRequest.setEntity(entity);
var response = client.execute(postRequest);

很好,告诉我我的KeyCloak设置是正确的。我现在要做的是从SOAP请求中提取证书并将其转发到KeyCloak调用。我已经使用拦截器完成了此操作,然后从这样的请求中提取证书:

if (httpRequest instanceof HttpServletRequest request
        && request.getAttribute("javax.servlet.request.ssl_session_mgr") instanceof SSLSupport sslSupport
        && sslSupport.getLocalCertificateChain() != null
) {
    for (var cert : sslSupport.getLocalCertificateChain()) {
        var keystore = KeyStore.getInstance("PKCS12");
        keystore.load(null, "passphrase".toCharArray());
        keystore.setCertificateEntry("1", cert);
        // then use the same code as before for calling keycloak
    }
}

但是现在我得到{“ error_description”:“ X509客户端证书”,“错误”:“ Invalid_request”}。研究它,我意识到,两个密钥店之间的主要区别是,由httprequest创建的一个不包含私钥,所以我怀疑这是它不起作用的原因。我在第一个示例中使用的keystore.pfx仅包含客户端证书btw。

有没有办法使其像这样起作用,还是我的整个方法完全错误?因为那是我开始怀疑的。如果是这样,我该如何解决?

I know my way around Java but I'm fairly inexperienced when it comes to the topic of SSL certificates. So my whole approach may be complete and utter nonsense.

What I'm trying to achieve is the following: I have a webservice build with Apache CXF in a Spring Boot application. That webservice is called a x509 client certificate and I want to use that certificate to get a JWT from a Keycloak instance which I have already configured. Getting the token from keycloak works when I do it like this:

var keystore = KeyStore.getInstance("PKCS12");
keystore.load(new ClassPathResource("keystore.pfx").getInputStream(), "myPassphrase".toCharArray());
HttpClient client = HttpClients.custom().setSSLContext(new SSLContextBuilder()
    .loadTrustMaterial(new ClassPathResource("truststore.jks").getFile(), "trustStorePW".toCharArray())
        .loadKeyMaterial(keystore, "myPassphrase".toCharArray())
        .build()
    ).setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE).build();

var postRequest = new HttpPost("https://localhost:8443/realms/master/protocol/openid-connect/token");
postRequest.addHeader("Content-Type", "application/x-www-form-urlencoded");
var entity = new StringEntity("grant_type=password&client_id=my-client&client_secret=my-secret");
postRequest.setEntity(entity);
var response = client.execute(postRequest);

That's fine and tells me that my keycloak setup is correct. What I'm trying to do now is to extract the certificate from the SOAP request and forward it to the keycloak call. I've done this with an interceptor and pull the certificate from the request like this:

if (httpRequest instanceof HttpServletRequest request
        && request.getAttribute("javax.servlet.request.ssl_session_mgr") instanceof SSLSupport sslSupport
        && sslSupport.getLocalCertificateChain() != null
) {
    for (var cert : sslSupport.getLocalCertificateChain()) {
        var keystore = KeyStore.getInstance("PKCS12");
        keystore.load(null, "passphrase".toCharArray());
        keystore.setCertificateEntry("1", cert);
        // then use the same code as before for calling keycloak
    }
}

But now I get {"error_description":"X509 client certificate is missing.","error":"invalid_request"}. Looking into it I realize that the main difference between the two keystores is that the one created from the HttpRequest does not contain the private key, so I suspect that's the reasons it doesn't work. The keystore.pfx I used in the first example contains only the client certificate btw.

Is there a way to make it work like this or is my whole approach completely wrong? Because that's what I'm starting to suspect. And if so, how could I solve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文