java - 运行 HTTPS 服务器时出现问题

标签 java http ssl https

我使用示例here编写了HTTPS服务器.

服务器代码:

public class HTTPSServer {

public static void main(String[] args) throws Exception {
    HttpsServer server = HttpsServer.create(new InetSocketAddress(8080), 5);
    server.createContext("/", new MyHandler());

    char[] storepass = "storepass".toCharArray();
    char[] keypass = "serverpass".toCharArray();

    KeyStore ks = KeyStore.getInstance("JKS");
    ks.load(HTTPSServer.class.getClassLoader().getResourceAsStream("web-vision.jks"), storepass);

    KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
    kmf.init(ks, keypass);

    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(kmf.getKeyManagers(), new TrustManager[]{}, null);

   server.setHttpsConfigurator(new HttpsConfigurator(sslContext) {

       @Override
       public void configure (HttpsParameters params) {

           // get the remote address if needed
           InetSocketAddress remote = params.getClientAddress();

           SSLContext c = getSSLContext();

           // get the default parameters
           SSLParameters sslparams = c.getDefaultSSLParameters();

           params.setSSLParameters(sslparams);
           // statement above could throw IAE if any params invalid.
           // eg. if app has a UI and parameters supplied by a user.

       }
   });

    ExecutorService executor = Executors.newFixedThreadPool(5);
    server.setExecutor(executor); // creates a default executor
    server.start();
    executor.awaitTermination(Integer.MAX_VALUE, TimeUnit.DAYS);

}

static class MyHandler implements HttpHandler {
    public void handle(HttpExchange t) throws IOException {

      String response = "This is the response";
      t.sendResponseHeaders(200, response.length());
      OutputStream os = t.getResponseBody();
      os.write(response.getBytes());
    }
}

对于此服务器,我使用以下命令创建了一个包含 key 的文件:

keytool -genkey -keystore web-vision.jks -dname "CN=localhost, OU=gg, O=NA, L=Unknown, ST=Unknown, C=RU" -storepass storepass -alias server-test -keypass serverpass

接下来,我将此文件放入项目资源中。

然后我启动此服务器并尝试连接到它并通过访问 https://10.155.26.68:8080/https://localhost:8080/来获取答案,但没有应答,服务器不可用。

在此之前,我实现了最简单的 HTTP 服务器并且运行良好。

使用curl 连接到HTTPS 服务器会产生此错误:

curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to 10.155.26.68:8080

screenshot of calling curl

更新:

感谢您的帮助,但只有使用以下命令创建新证书才能解决问题:

keytool -v -genkey -dname "CN=localhost, OU=Developers, O=NA, L=Ufa, C=RB" -alias parent -storetype jks -keystore vision.jks -validity 365 -keyalg RSA -keysize 2048 -storepass mystorepass -keypass mykeypass

我刚刚学习 SSL,也许第一个证书创建不正确。

最佳答案

您在使用curl时遇到SSL_ERROR_SYSCALL的可能原因是,在使用keytool创建证书时,您没有指定要使用的算法。

在这种情况下,keytool 默认使用 DSA .

然后,在与curl的握手阶段,服务器找不到通用的身份验证方案并抛出异常:

javax.net.ssl.SSLHandshakeException: No available authentication scheme
        at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131)
        at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:117)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:308)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:264)
        at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:255)
        at java.base/sun.security.ssl.CertificateMessage$T13CertificateProducer.onProduceCertificate(CertificateMessage.java:945)
        at java.base/sun.security.ssl.CertificateMessage$T13CertificateProducer.produce(CertificateMessage.java:934)
        at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:436)
        at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1224)
        at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1160)
        at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:849)
        at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:810)
        at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:392)
        at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:448)
        at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1065)
        at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask$DelegatedAction.run(SSLEngineImpl.java:1052)
        at java.base/java.security.AccessController.doPrivileged(Native Method)
        at java.base/sun.security.ssl.SSLEngineImpl$DelegatedTask.run(SSLEngineImpl.java:999)
        at jdk.httpserver/sun.net.httpserver.SSLStreams.doHandshake(SSLStreams.java:464)
        at jdk.httpserver/sun.net.httpserver.SSLStreams.recvData(SSLStreams.java:418)
        at jdk.httpserver/sun.net.httpserver.SSLStreams$InputStream.read(SSLStreams.java:522)
        at jdk.httpserver/sun.net.httpserver.SSLStreams$InputStream.read(SSLStreams.java:591)
        at jdk.httpserver/sun.net.httpserver.Request.readLine(Request.java:80)
        at jdk.httpserver/sun.net.httpserver.Request.<init>(Request.java:50)
        at jdk.httpserver/sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:551)
        at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
        at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
        at java.base/java.lang.Thread.run(Thread.java:834)

由于此异常是由 sun.net.httpserver.ServerImpl$Exchange.run 在日志级别 FINER 记录的,因此很难检测到。

正如您所想,使用 -keyalg RSA 调用 keytool 来生成证书,使服务器和客户端找到解决该问题的身份验证方案:

keytool -genkeypair -keyalg RSA -alias selfsigned -keystore keystore.jks -storepass secret_password -dname "CN=localhost, OU=Developers, O=NA, L=Ufa, C=RB"

关于java - 运行 HTTPS 服务器时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56414643/

相关文章:

java生成动态csv文件供下载

http - 如何在 Google Glass GDK 上发出 HTTP GET 请求

ssl - 识别安全 html 请求中的不安全内容

java - SSLPeerUnverifiedException : peer not authenticated WITH VALID CERTIFICATE

java - 如何在 Apache Olingo 中创建实体?

java - 如何实现用户验证以仅接受少数字母有效

java - 如何在 HTML 页面上正确合并小程序?

java - 调试问题关闭 Apache Tomcat

http - 如何在 Jolie 编程语言中获取服务的 http header

java - 通过SSL使用JMS连接到WebSphere MQ 7.0