休息轻松https电话,如何接受所​​有证书

时间:2013-09-19 12:39:38

标签: java rest ssl

我试图通过以下方式使用jboss rest来调用REST服务

    public ETTestCasePackage getPackageById(String packageId) throws PackageNotFound {

    ClientRequest req = new ClientRequest("https://facebook/api");
    req.header("Authorization", "Basic " + EztrackerConstants.base64AuthenticationValue);
    req.pathParameter("id", packageId);
    ETTestCasePackage etPackage = null;
    try {
        logger.info("invoking "+req.getUri());
        //ProxyFactory.create
        ClientResponse<ETTestCasePackage> res = req.get(ETTestCasePackage.class);
        etPackage = res.getEntity();
    } catch (Exception e) {
        logger.debug("Not able to retrieve details for testcase package having id = " + packageId, e);
        throw new PackageNotFound("Package with id " + packageId + " not found", e);
    }
    return etPackage;

}

但上面的代码显然抛出“peer not authenticated”;

 javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
    at sun.security.ssl.SSLSessionImpl.getPeerCertificates(Unknown Source)
    at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:126)
    at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:437)
    at 

我可以将相应的证书添加到我的本地java安全jks来解决这个问题。 但我可能会运行这么多机器,所以不能对所有机器都这样做。所以我想让我的http客户端通过覆盖http检查来接受所有请求。

但是对于简单的httprequest,我无法找到办法。是否会有人帮助我轻松完成这项休息。

先谢谢, SYAM。

我已经尝试过这段代码调用实际代码来忽略但仍然没有覆盖默认设置。任何想让它为这个休息的客户工作的想法。

    private void test(){

        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                    public void checkClientTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                    }
                    public void checkServerTrusted(
                        java.security.cert.X509Certificate[] certs, String authType) {
                    }
                }
            };

            // Install the all-trusting trust manager
            try {
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, new java.security.SecureRandom());
                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
            } catch (Exception e) {
            }

    }

    static {
        //for localhost testing only
        javax.net.ssl.HttpsURLConnection.setDefaultHostnameVerifier(
        new javax.net.ssl.HostnameVerifier(){

            public boolean verify(String hostname,
                    javax.net.ssl.SSLSession sslSession) {

                return true;
            }
        });
    }

}

4 个答案:

答案 0 :(得分:5)

使用已签名的证书作为计划A.作为计划B,当您定位另一个您无法控制的系统的暂存版本时,可以使用以下解决方案。

对于Resteasy 3,您需要为客户端实例提供您自己的所有信任的Httpclient。 当然你不应该在生产中使用它,所以一定不要硬化它。

通常(使用jax-rs 2.0)你会像这样初始化一个客户端:

javax.ws.rs.client.Client client = javax.ws.rs.client.ClientBuilder.newClient();

对于所有信任客户,请按如下所示进行替换:

Client client = null;
if (config.trustAllCertificates) {
  log.warn("Trusting all certificates. Do not use in production mode!");
  ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(createAllTrustingClient());
  client = new ResteasyClientBuilder().httpEngine(engine).build();
}
else {
  client = ClientBuilder.newClient();
}

createAllTrustingClient()看起来像这样:

private DefaultHttpClient createAllTrustingClient() throws GeneralSecurityException {
  SchemeRegistry registry = new SchemeRegistry();
  registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));

  TrustStrategy trustStrategy = new TrustStrategy() {
    public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
      return true;
    }
  };
  SSLSocketFactory factory = new SSLSocketFactory(trustStrategy, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER );
  registry.register(new Scheme("https", 443, factory));

  ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(registry);
  mgr.setMaxTotal(1000);
  mgr.setDefaultMaxPerRoute(1000);

  DefaultHttpClient client = new DefaultHttpClient(mgr, new DefaultHttpClient().getParams());
  return client;
}

万一你弄清楚类的包名,以下是相关的导入:

import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;

import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine;

供参考:

答案 1 :(得分:0)

最简单的方法是在要部署服务的每台计算机上获取具有正确DN并由公共CA签名的正确证书。这是官僚主义和讨厌的,可能花费真金白银,但它绝对是最简单整体。

否则,您必须将客户端配置为具有不实际验证的验证程序。这是危险的,因为任何人(包括随机黑客,有组织的犯罪分子和狡猾的政府机构)都可以制作自签名证书,并且没有切实可行的方法来检测他们是否已经这样做了。除了通过遍历并分发到每个客户端之外,将使用永远的整个服务器证书列表(允许验证者使用俱乐部门卫技术进行检查:“如果你不在名单上,你不会进来“)。

验证者在技术上将成为某种X509TrustManager的实例。

答案 2 :(得分:0)

添加Arnelism的答案:如果您使用的是nulllock的依赖项),您会发现ThreadSafeClientConnManagerhttpclient-4.2.6.jar。您可以将其修改为BasicClientConnectionManagerPoolingClientConnectionManager

resteasy-jaxrs-3.0.10.Final.jar

答案 3 :(得分:0)

有必要破解ApacheHttpClient4Executor,下面的代码可以使用HTTPS并提供ClientRequest:

    UriBuilder uri = UriBuilder.fromUri(request.endpoint() + request.path());
    System.out.println(request.endpoint() + request.path());

    class ApacheHttpClient4Executor2 extends ApacheHttpClient4Executor {
    }

    ApacheHttpClient4Executor2 executor = new ApacheHttpClient4Executor2();
    Scheme http = new Scheme("http", 80, PlainSocketFactory.getSocketFactory());

    TrustStrategy trustStrategy = new TrustStrategy() {
        @Override
        public boolean isTrusted(java.security.cert.X509Certificate[] chain, String authType)
                throws CertificateException {
            return true;
        }
    };

    SSLSocketFactory factory = null;
    try {
        factory = new SSLSocketFactory(trustStrategy, SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
    } catch (KeyManagementException | UnrecoverableKeyException | NoSuchAlgorithmException | KeyStoreException e1) {

        e1.printStackTrace();
    }
    Scheme https = new Scheme("https", 443, factory);

    executor.getHttpClient().getConnectionManager().getSchemeRegistry().register(http);
    executor.getHttpClient().getConnectionManager().getSchemeRegistry().register(https);

    ClientRequest client = new ClientRequest(uri, executor, providerFactory);