Java 具有SSL相互身份验证的Jersey客户端

Java 具有SSL相互身份验证的Jersey客户端,java,ssl,jersey,keytool,jersey-client,Java,Ssl,Jersey,Keytool,Jersey Client,我有一个用java编写的代码,我使用jersey客户端,我尝试进行相互认证,所以我还有一个.jks,其中包含CA签署的证书,这是我的代码 @SuppressWarnings("static-access") @POST @Path("PruebaPlumaCalva") public Response testPlumaCalva(String jsonObject) { // ClientBuilder.newClient(). logger.debug("Test");

我有一个用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;
}
@SuppressWarnings(“静态访问”)
@职位
@路径(“PruebaPlumaCalva”)
公共响应testPlumaCalva(字符串jsonObject)
{
//ClientBuilder.newClient()。
调试(“测试”);
Map payload=newhashmap();
有效载荷。放置(“文档类型”,x);
有效载荷。put(“文件编号”,xxxxxx);
有效载荷。出售(“合伙人”、“xxx”);
有效载荷。卖出(“交易ID”、“xxxxx”);
logger.debug(“Mis parametros子:”+有效载荷);
字符串json=null;
尝试
{
json=(新的ObjectMapper()).writeValueAsString(有效负载);
}
捕获(JsonProcessingException e)
{
}
HttpAuthenticationFeature=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”).KeyStore.keyPassword(“123456”).createSSLContext();
SSLContext scl=SslConfigurator.newInstance().trustStoreFile(“/cdrive/f_drive/Pos.jks”).trustStorePassword(“123456”).keystrefile(“/cdrive/f_drive/Pos.jks”).keyPassword(“test”).createSSLContext();
Client Client=ClientBuilder.newBuilder()
.sslContext(scl)
.build();
客户端。注册(功能);
WebTarget WebTarget=client.target(“xxxxxxxx”);
Invocation.Builder invocationB=webTarget.request(MediaType.APPLICATION\u JSON\u TYPE);
Response=invocationB.post(Entity.json(json));
JsonNode JsonNode=bonusUtilities.createJsonNode(响应);
debug(“JsonNode应答”+JsonNode);
int x=0;
返回响应;
}

所以当我只使用1个证书执行代码时,他工作得很好,但当我有2个证书时,他不工作,我认为问题是.jk不知道他必须使用哪个证书,但我不知道如何指定他必须使用哪个证书,我已经看了很多论坛,但我看不到有人能为我的问题提供解决方案

我也有同样的问题,多亏了这一点,我才能解决它。 基本上,没有办法做到“开箱即用”,您必须实现自己的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());