使用Java使用证书在https上使用RESTful服务 [英] Consuming RESTful service over https with certificate using Java
问题描述
我是REST服务的新用户。我需要使用通过Jersey生成的RESTful API服务。问题来了,因为该服务托管在远程主机上,并且需要使用证书进行https访问。
I'm a new user to REST services. I need to consume a RESTful API service generated with Jersey. The problem comes because that service is hosted on remote host and it requires https access with certificate.
我从组织获得了证书,并且能够访问该REST我的任何浏览器都使用API服务(在上面设置了证书)。
I got my certificate from the organization and i'm able to access that REST API service with any of my browsers (with certificate set on them).
我在这里阅读了很多文章,并且已经关注了这个主题的答案:
在Java中将HTTPS与REST一起使用
I've read lot of posts over here, and I've followed the answer on this topic: Using HTTPS with REST in Java
现在,我已经在Java密钥库中设置了证书。但是我不知道如何在Java程序上使用它,因此它恰好使用了我需要进行https连接的证书。
Now I've my certificate setup on my Java Keystore. But i don't know how to use that on my Java program so it uses exactly the certificate i need to do the https connection.
这是我的简单连接代码
package rest.test.first;
import java.net.URI;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.UriBuilder;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.client.config.ClientConfig;
import com.sun.jersey.api.client.config.DefaultClientConfig;
public class TestClient{
public static void main(String[]args){
ClientConfig config= new DefaultClientConfig();
Client client=Client.create(config);
WebResource service=client.resource(getBaseURI());
//Fluentinterfaces
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_PLAIN).get(ClientResponse.class).toString());
//Getplaintext
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_PLAIN).get(String.class));
//GetXML
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_XML).get(String.class));
//TheHTML
System.out.println(service.path("rest").path("hello").accept(MediaType.TEXT_HTML).get(String.class));
}
private static URI getBaseURI(){
return UriBuilder.fromUri("http://localhost:8080/rest.test").build();
}
}
我了解了使用系统集属性指定带有以下代码的密钥库的路径:
I'v read about using system set properties to specify path to keystore with this code:
System.setProperty("javax.net.ssl.keyStore", "/path/to/keystore.jks");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
在连接到远程服务器时,我仍然收到401错误。
I still get 401 Error on connection to the remote server.
但是然后我不知道如何使用我在密钥库上的证书进行SSL连接。
我也一直在阅读有关为此目的使用sslSocketFactory的信息,但我却无法按照这篇文章中的说明进行操作:如何在特定连接上使用不同的证书?
But then i don't know how to make SSL connection using my certificate on keystore. I've been also reading about using sslSocketFactory for this purpose but i couldn't make it work as explained on this post: How can I use different certificates on specific connections?
我已经设法使用以下代码从密钥库中检索了我的证书。.现在,我只需要知道如何在连接中使用它:
I've managed to retrieve my cert from keystore with this code.. now I just need to know how to use it in connection:
package rest.test.first;
import java.io.FileInputStream;
import java.security.KeyStore;
import java.security.cert.Certificate;
public class keystore {
public static void main(String[] args) throws Exception {
String keystoreFilename = "/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts";
char[] password = "changeit".toCharArray();
String alias = "remote_https_server";
FileInputStream fIn = new FileInputStream(keystoreFilename);
KeyStore keystore = KeyStore.getInstance("JKS");
keystore.load(fIn, password);
Certificate cert = keystore.getCertificate(alias);
System.out.println(cert);
}
}
好吧,这是我写的最后一个脚本。我可以连接到https站点,但仍然无法连接到https站点,这需要发送我的证书进行身份验证。
Ok that's the last script I've wrote. I can connect to https sites but i still can't connect to https sites which require to send my certificate to authenticate.
package rest.test.first;
import java.io.*;
import java.net.*;
import java.security.*;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
public class urlConnection{
public static void main(String args[]) throws Exception {
System.setProperty("javax.net.ssl.trustStore", "/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts");
System.setProperty("javax.net.ssl.trustStorePassword", "changeit");
Security.addProvider(new com.sun.net.ssl.internal.ssl.Provider());
//TrustStore..
char[] passphrase = "changeit".toCharArray(); //password
KeyStore keystore = KeyStore.getInstance("JKS");
//KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keystore.load(new FileInputStream("/usr/lib/jvm/jdk1.6.0_32/jre/lib/security/cacerts"), passphrase); //path
//TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509"); //instance
TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
tmf.init(keystore);
SSLContext context = SSLContext.getInstance("TLS");
TrustManager[] trustManagers = tmf.getTrustManagers();
context.init(null, trustManagers, null);
SSLSocketFactory sf = context.getSocketFactory();
URL url = new URL("https://www.google.es");
HttpsURLConnection httpsCon = (HttpsURLConnection) url.openConnection();
httpsCon.setSSLSocketFactory(sf);
httpsCon.setRequestMethod("GET");
/*InputStream inStrm = httpsCon.getInputStream();
System.out.println("\nContent at " + url);
int ch;
while (((ch = inStrm.read()) != -1)){
System.out.print((char) ch);
inStrm.close();
}*/
System.out.println("Response Message is " + httpsCon.getResponseMessage());
}
}
推荐答案
假设您正在将此代码部署在服务器上并且已正确完成了其他所有操作(例如正确生成密钥库核心并将其放置在服务器可以访问的位置,请使用与代码相同的Java版本来生成密钥库),然后我认为您需要做的是添加以下内容
Assuming that you are deploying this code on a server and you have done Everything else correctly (Like generating keystore core correctly and placing it at a location where it can be accessed by your server ,using same java version as your code to generate the keystore )then i think what you need to do is add following
<Connector SSLEnabled="true" clientAuth="false" keystoreFile="pathToKeystore" keystorePass="password" maxThreads="150" port="443" protocol="HTTP/1.1" scheme="https" secure="true" sslProtocol="TLS"/>
b
$ b
in server.xml of your Server instance on which you are running the client and
<Connector connectionTimeout="20000" port="80" protocol="HTTP/1.1" redirectPort="8443"/>
IMP:如果您将Skype与此代码一起使用,请确保(取消选中)将默认值更改为它还使用相同的端口(80和443)进行其他连接
IMP: If you are using Skype alongside this code be sure to (uncheck) change the default value as it also uses the same ports (80 and 443) for additional connections
这篇关于使用Java使用证书在https上使用RESTful服务的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!