我可以轻松地创建一个我需要的HTTP纯Java服务器。但是,像这样的HTTPS服务器:
package httpstest;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsServer;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.security.KeyStore;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManagerFactory;
public class HttpsTest {
public static void main(String[] args) throws Exception {
HttpsServer server = HttpsServer.create(new InetSocketAddress(8000), 0);
server.setHttpsConfigurator(new HttpsConfigurator(createSSLContext()));
server.createContext("/test", new TestHandler());
server.setExecutor(null); // creates a default executor
server.start();
}
private static SSLContext createSSLContext() throws Exception {
CertificateFactory cf = CertificateFactory.getInstance("X.509");
InputStream is = new FileInputStream("server.crt");
InputStream caInput = new BufferedInputStream(is);
Certificate ca = cf.generateCertificate(caInput);
caInput.close();
// Create a KeyStore containing our trusted CAs
String keyStoreType = KeyStore.getDefaultType();
KeyStore keyStore = KeyStore.getInstance(keyStoreType);
keyStore.load(null, null);
keyStore.setCertificateEntry("ca", ca);
// Create a TrustManager that trusts the CAs in our KeyStore
String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
tmf.init(keyStore);
// Create an SSLContext that uses our TrustManager
SSLContext context = SSLContext.getInstance("TLS");
context.init(null, tmf.getTrustManagers(), null);
return context;
}
static class TestHandler implements HttpHandler {
@Override
public void handle(HttpExchange t) throws IOException {
String response = "Successfully connected!";
t.sendResponseHeaders(200, response.length());
OutputStream os = t.getResponseBody();
os.write(response.getBytes());
os.close();
}
}
}
将编译并运行服务器端而没有错误,但会从浏览器中产生SSL错误。似乎服务器期望浏览器具有相同的证书。我希望任何浏览器都通过HTTPS连接到它而没有安装证书(就像有人会连接到https://www.google.com)
答案 0 :(得分:1)
有可能。以下是关键代码:
SSLContext sslContext = SSLContext.getInstance("TLS");
char[] keystorePassword = "password".toCharArray();
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(new FileInputStream("filename.jks"), keystorePassword);
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
kmf.init(ks, keystorePassword);
sslContext.init(kmf.getKeyManagers(), null, null);
HttpsConfigurator configurator = new HttpsConfigurator(sslContext);
答案 1 :(得分:0)
当您是服务器时,您需要在KeyManager
中安装私有证书。 TrustManager
用于与私有客户端证书相对应的公共证书。显然,如果您不希望浏览器投诉,则需要来自可信CA的私有证书。
答案 2 :(得分:0)
当您使用HTTPS连接到Google时,您的浏览器中的证书已经可用,因为它是由受信任的CA签名的证书。
要执行您的意图,您必须使用已签名的证书(您需要为此付费或某些人使用来自StarCom的免费签名证书,但我不确定最后一个)