0

我正在尝试通过以下方式使用 jboss rest easy 调用 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,我无法找到一种方法来做到这一点。有人会帮我做这件事吗?

在此先感谢,赛姆。

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

    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

4 回答 4

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;

以供参考:

于 2014-03-16T22:45:54.637 回答
0

最简单的方法是在部署服务的每台机器上获取正确的证书、正确的 DN 并由公共 CA 签名。这是官僚和烦人的,可能要花真钱,但总的来说绝对是最简单的。

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

验证器在技术上将是X509TrustManager.

于 2013-09-19T13:21:24.823 回答
0

加起来 Arnelism 的答案:如果您正在使用httpclient-4.2.6.jar(这是 的依赖项resteasy-jaxrs-3.0.10.Final.jar),您会发现ThreadSafeClientConnManager@Deprecated. 您可以将其修改为BasicClientConnectionManagerPoolingClientConnectionManager改为:

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

    TrustStrategy trustStrategy = new TrustStrategy() {
        @Override
        public boolean isTrusted(java.security.cert.X509Certificate[] arg0,
                String arg1) throws java.security.cert.CertificateException {
            return true;
        }
    };
    SSLSocketFactory factory = new SSLSocketFactory(
                                    trustStrategy,
                                    SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER
                               );
    registry.register(new Scheme("https", 443, factory));

    BasicClientConnectionManager mgr = new BasicClientConnectionManager(registry);

    DefaultHttpClient client =
                new DefaultHttpClient(mgr, new DefaultHttpClient().getParams());
    return client;
}
于 2015-05-13T07:55:08.850 回答
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);
于 2015-12-02T16:28:18.520 回答