可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
i am trying to call the REST service using jboss rest easy in the following way
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;
}
but the above code obviously throw "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
I can add the respective cert to my local java security jks to solve this.
but i may run this so many machines, so cannot do that to all machines. so i want to make my http client accept all request by overridding the http checks.
but for rest easy httprequest, i am not able to find a way to do this. would some one help me in doing for this rest easy.
Thanks in Advance,
syam.
I have tried this piece of code calling the actual code for ignoring but still didn't override the default settings. any idea for to make it work for this rest easy client.
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;
}
});
}
}
回答1:
Use signed certs as a plan A. As a plan B, when targeting a staging version of another system that you do not control for example, you can use the following solution.
For Resteasy 3, you need to provide your own all-trusting Httpclient to the client instance.
Of course you should never use that in production, so make sure not to hardoce it.
Normally (using jax-rs 2.0) you'd initialize a client like this:
javax.ws.rs.client.Client client = javax.ws.rs.client.ClientBuilder.newClient();
For all trusting client, replace it as follows:
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();
}
The createAllTrustingClient() would look like this:
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;
}
Just in case you have trouble figuring out the package names of the classes, here are the relevant imports:
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;
For reference:
- https://docs.jboss.org/resteasy/docs/3.0-beta-3/userguide/html/RESTEasy_Client_Framework.html#transport_layer
回答2:
The easiest method is to get a proper certificate, with a correct DN and signed by a public CA, on each machine on which you are deploying the service. It's bureaucratic and annoying and probably costs real money, but it is definitely easiest overall.
Otherwise, you have to configure the clients to have a verifier that doesn't actually verify. That's dangerous, since anyone at all (including random hackers, organised criminals and dodgy government agencies) can make a self-signed certificate and there's no practical way to detect that they have done so. Except by going through and distributing to every client the entire list of server certificates that will ever be used (allowing the verifier to do its check using the club doorman technique: “if you're not on the list, you're not coming in”).
The verifier is technically going to be some kind of instance of X509TrustManager
.
回答3:
To add up on Arnelism's answer: if you are using httpclient-4.2.6.jar
(which is a dependency for resteasy-jaxrs-3.0.10.Final.jar
), you will find that ThreadSafeClientConnManager
is @Deprecated
. You can modify it to BasicClientConnectionManager
or PoolingClientConnectionManager
instead:
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;
}
回答4:
It's necessary to hack the ApacheHttpClient4Executor, the code below is work with HTTPS and will provide a 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);