我有一个用 java 编写的代码,我使用的是 jersey 客户端,我尝试进行相互认证,所以我还有一个 .jks,其中包含我由 CA 签名的证书,所以这是我的代码
@SuppressWarnings("static-access")
@POST
@Path("PruebaPlumaCalva")
public Response testPlumaCalva(String jsonObject)
{
// ClientBuilder.newClient().
logger.debug("Test");
Map<String, Object> payload = new HashMap<String, Object>();
payload.put("documentType", x);
payload.put("documentNumber", xxxxxx);
payload.put("partner", "xxx");
payload.put("transactionId", "xxxxx");
logger.debug("Mis parametros son:" + payload);
String json = null;
try
{
json = (new ObjectMapper()).writeValueAsString(payload);
}
catch (JsonProcessingException e)
{
}
HttpAuthenticationFeature feature = HttpAuthenticationFeature.basic("xxxxx", "xxxx");
//SSLContext scl = SslConfigurator.newInstance().trustStoreFile("C:/Users/juan.rojas/Documents/Juan José/Proyectos/PagosMoviles/KeyStore.jks").trustStorePassword("123456").keyStoreFile("C:/Users/juan.rojas/Documents/Juan José/Proyectos/PagosMoviles/KeyStore.jks").keyPassword("123456").createSSLContext();
SSLContext scl = SslConfigurator.newInstance().trustStoreFile("/cdrive/f_drive/Pos.jks").trustStorePassword("123456").keyStoreFile("/cdrive/f_drive/Pos.jks").keyPassword("test").createSSLContext();
Client client = ClientBuilder.newBuilder()
.sslContext(scl)
.build();
client.register(feature);
WebTarget webTarget = client.target("xxxxxxxx");
Invocation.Builder invocationB = webTarget.request(MediaType.APPLICATION_JSON_TYPE);
Response response = invocationB.post(Entity.json(json));
JsonNode jsonNode = bonusUtilities.createJsonNode(response);
logger.debug("JsonNode Answer" + jsonNode);
int x = 0;
return response;
}
因此,当我仅使用 1 个证书执行该代码时,他工作正常,但当我有 2 个证书时,他不工作,我认为问题是 .jks 不知道他必须使用哪个证书,但我不知道如何要指定他必须使用哪一个,我已经看了很多论坛,但我看不到有人能为我提供问题的解决方案
最佳答案
我遇到了同样的问题,多亏了这个 answer 可以解决它. 基本上,没有办法“开箱即用”,您必须实现自己的 KeyManager。
我进一步简化了链接的答案,代码如下所示:
public class FilteredKeyManager implements X509KeyManager {
private final X509KeyManager originatingKeyManager;
public FilteredKeyManager(X509KeyManager originatingKeyManager) {
this.originatingKeyManager = originatingKeyManager;
}
@Override
public String chooseClientAlias(String[] arg0, Principal[] arg1, Socket arg2) {
return "yourAliasHere";
}
}
对于其余的覆盖方法,只需调用 originatingKeyManager。
要创建 SSLContext,我没有使用 SSLConfigurator,但参数是相同的(路径和密码)。
// Init keystore
KeyStore ks = KeyStore.getInstance("JKS");
FileInputStream ksFile = new FileInputStream("yourKeystorePath");
ks.load(ksFile, "keystorePassword".toCharArray());
KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
kmf.init(ks, pass);
// Init truststore
KeyStore trustKeystore = KeyStore.getInstance("JKS"));
FileInputStream tsFile = new FileInputStream("yourTruststorePath"));
trustKeystore.load(tsFile, "truststorePassword".toCharArray());
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(trustKeystore);
// Create instance of custom KeyManager
KeyManager[] km = new KeyManager[] { new FilteredKeyManager((X509KeyManager) kmf.getKeyManagers()[0]) };
// Create SSLContext using custom KeyManager
SSLContext context = SSLContext.getInstance("TLSv1");
context.init(km, ts, new SecureRandom());
关于java - 具有 SSL 相互身份验证的 Jersey 客户端,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55497171/