如何在Java中使用Webclient添加CA证书和客户端证书

如何在Java中使用Webclient添加CA证书和客户端证书,java,api,post,certificate,webclient,Java,Api,Post,Certificate,Webclient,我正在尝试使用Java中的Webclient编写API调用。目前,我很难找到关于如何向Webclient添加证书的文档。我想提供一个PEM格式的CA证书文件,以及一个客户端证书,其中我将提供一个主机、一个CRT文件、一个密钥文件和一个密码短语。我已经在postman中使用了这个设置,但是我想将它转移到Java应用程序中。下面是我的代码 Gson gson = new Gson(); LinkedHashMap<String, Object> reqBody

我正在尝试使用Java中的Webclient编写API调用。目前,我很难找到关于如何向Webclient添加证书的文档。我想提供一个PEM格式的CA证书文件,以及一个客户端证书,其中我将提供一个主机、一个CRT文件、一个密钥文件和一个密码短语。我已经在postman中使用了这个设置,但是我想将它转移到Java应用程序中。下面是我的代码

       Gson gson = new Gson();
       LinkedHashMap<String, Object> reqBody
               = new LinkedHashMap<String, Object>();
       LinkedHashMap<String, String> variables
               = new LinkedHashMap<String, String>();
       reqBody.put("variables", variables);



       WebClient webClient = WebClient.builder()
               .baseUrl("sampleurl.com")
               .defaultHeader(HttpHeaders.USER_AGENT, "Spring 5 WebClient")
               .defaultHeader(HttpHeaders.ACCEPT, "application/json")
               .defaultHeader(HttpHeaders.CONTENT_TYPE, "application/json")
               .build();


       return webClient.post()
               .uri("/api")
               .headers(headers -> headers.setBasicAuth("userName", "password"))
               .body(Mono.just(reqBody), LinkedHashMap.class)//if directly putting the map doesn't work
               //can also convert to json string then to monoflux
               .retrieve()
               .bodyToMono(String.class);
Gson-Gson=new-Gson();
LinkedHashMapReqBody
=新LinkedHashMap();
LinkedHashMap变量
=新LinkedHashMap();
reqBody.put(“变量”,变量);
WebClient WebClient=WebClient.builder()
.baseUrl(“sampleurl.com”)
.defaultHeader(HttpHeaders.USER\u代理,“Spring5WebClient”)
.defaultHeader(HttpHeaders.ACCEPT,“应用程序/json”)
.defaultHeader(HttpHeaders.CONTENT_类型,“应用程序/json”)
.build();
返回webClient.post()
.uri(“/api”)
.headers(headers->headers.setBasicAuth(“用户名”、“密码”))
.body(Mono.just(reqBody),LinkedHashMap.class)//如果直接放置映射不起作用
//还可以转换为json字符串,然后再转换为monoflux
.retrieve()
.bodyToMono(String.class);

尽管michalk为webclient提供了一个ssl配置示例链接,但关于如何加载CA证书、密钥和密码短语的问题仍然没有答案

如果您只想加载pem格式化(ca和own trusted certificates)证书,那么可以使用jdk中可用的类。但是,您还希望将关键材料作为pem文件加载,这在jdk中的默认类中是不可能的。我推荐Bouncy castle用于此用例:

maven依赖项:


org.bouncycastle
bcpkix-jdk15on
import io.netty.handler.ssl.SslContext;
导入io.netty.handler.ssl.SslContextBuilder;
导入org.bouncycastle.asn1.pkcs.PrivateKeyInfo;
导入org.bouncycastle.jce.provider.BouncyCastleProvider;
导入org.bouncycastle.openssl.pemdeccryptorProvider;
导入org.bouncycastle.openssl.PEMEncryptedKeyPair;
导入org.bouncycastle.openssl.PEMKeyPair;
导入org.bouncycastle.openssl.PEMParser;
导入org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
导入org.bouncycastle.openssl.jcajce.JceOpenSSLPKCS8DecryptorProviderBuilder;
导入org.bouncycastle.openssl.jcajce.jcepedecryptorProviderBuilder;
导入org.bouncycastle.operator.InputDecryptorProvider;
导入org.bouncycastle.operator.operator CreationException;
导入org.bouncycastle.pkcs.PKCS8EncryptedPrivateKeyInfo;
导入org.bouncycastle.pkcs.PKCSException;
导入org.springframework.http.client.reactive.ReactorClientHttpConnector;
导入org.springframework.web.reactive.function.client.WebClient;
导入reactor.netty.http.client.HttpClient;
导入javax.net.ssl.KeyManagerFactory;
导入javax.net.ssl.TrustManagerFactory;
导入java.io.ByteArrayInputStream;
导入java.io.IOException;
导入java.io.StringReader;
导入java.security.KeyStore;
导入java.security.KeyStoreException;
导入java.security.NoSuchAlgorithmException;
导入java.security.PrivateKey;
导入java.security.UnrecoverableKeyException;
导入java.security.cert.Certificate;
导入java.security.cert.CertificateException;
导入java.security.cert.CertificateFactory;
导入java.util.ArrayList;
导入java.util.Base64;
导入java.util.List;
导入java.util.Objects;
导入java.util.UUID;
导入java.util.regex.Matcher;
导入java.util.regex.Pattern;
类应用程序{
私有静态最终BouncyCastleProvider BOUNCY_CASTLE_PROVIDER=新的BouncyCastleProvider();
私有静态最终JcaPEMKeyConverter KEY_CONVERTER=新的JcaPEMKeyConverter().setProvider(BOUNCY_CASTLE_PROVIDER);
私有静态最终字符串证书\u TYPE=“X.509”;
私有静态最终模式证书\u Pattern=Pattern.compile(----开始证书------(.*)----结束证书------),Pattern.DOTALL);
私有静态最终字符串NEW_LINE=“\n”;
私有静态最终字符串为空=”;
public static PrivateKey parsePrivateKey(字符串privateKeyContent,char[]keyPassword)引发IOException、PKCSException、OperatorCreationException{
PEMParser PEMParser=newpemparser(newstringreader(privateKeyContent));
PrivateKeyInfo PrivateKeyInfo=null;
Object Object=pemParser.readObject();
while(object!=null&&privateKeyInfo==null){
if(PrivateKeyInfo的对象实例){
privateKeyInfo=(privateKeyInfo)对象;
}else if(PEMKeyPair的对象实例){
privateKeyInfo=((PEMKeyPair)对象);
}else if(PKCS8EncryptedPrivateKeyInfo的对象实例){
InputDecryptoProvider InputDecryptoProvider=新的JCeopenssLPKCS8DecryptoProviderBuilder()
.setProvider(BOUNCY_CASTLE_PROVIDER)
.build(Objects.requirennull(keyPassword));
privateKeyInfo=((PKCS8EncryptedPrivateKeyInfo)对象)。解密privateKeyInfo(inputDecryptorProvider);
}else if(PEMEncryptedKeyPair的对象实例){
PEMDecryptorProvider PEMDecryptorProvider=新的JcePEMDecryptorProviderBuilder()
.setProvider(BOUNCY_CASTLE_PROVIDER)
.build(keyPassword);
PEMKeyPair PEMKeyPair=((PEMEncryptedKeyPair)对象)。decryptKeyPair(pemDecryptorProvider);
privateKeyInfo=pemKeyPair.getPrivateKeyInfo();
}
if(privateKeyInfo==null){
object=pemParser.readObject();
}
}
if(Objects.isNull(privateKeyInfo)){
抛出新的I