首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >HTTP错误400无效的SNI - Jetty HTTPS servlet

HTTP错误400无效的SNI - Jetty HTTPS servlet
EN

Stack Overflow用户
提问于 2021-11-12 15:20:44
回答 2查看 3.8K关注 0票数 5

我试图解决运行在HTTPS上的的一个问题。

它在浏览器中显示此错误页:

我所做的:

我创建了我的Keystore和Truststore,如下所述:How to generate keystore and truststore

  1. 两个文件都放在我的项目目录中,并编写了代码来加载这些文件。

代码语言:javascript
复制
package sk.cood.metahost.server;

import jakarta.servlet.ServletException;
import jakarta.servlet.annotation.WebServlet;
import jakarta.servlet.http.HttpServlet;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.eclipse.jetty.server.*;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.ssl.SslContextFactory;

import java.io.*;

@WebServlet(displayName = "MetaHostServlet", urlPatterns = { "/*" })
public class MetaHostServlet extends HttpServlet {
    private static File keyStoreFile;
    private static File trustStoreFile;

    public static void main(String[] args) throws Exception {
        loadKeyStores();

        Server server = new Server(8080);
        ServerConnector connector = createSSLConnector(server, "password", "password", false);
        server.addConnector(connector);

        ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS);
        context.addServlet(new ServletHolder(new MetaHostServlet()),"/*");
        context.setContextPath("/");
        server.setHandler(context);

        server.start();
        server.join();
    }

    private static void loadKeyStores() {
        keyStoreFile = new File("keystore.jks");
        trustStoreFile = new File("truststore.jks");
        if (!keyStoreFile.exists()) {
            throw new RuntimeException("Key store file does not exist on path '"+keyStoreFile.getAbsolutePath()+"'");
        }
        if (!trustStoreFile.exists()) {
            throw new RuntimeException("Trust store file does not exist on path '"+trustStoreFile.getAbsolutePath()+"'");
        }
    }

    private static ServerConnector createSSLConnector(Server server, String keyStorePassword, String trustStorePassword, boolean isClientAuthNeeded) {
        SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
        sslContextFactory.setKeyStorePath(keyStoreFile.getAbsolutePath());
        sslContextFactory.setKeyStorePassword(keyStorePassword);
        sslContextFactory.setTrustStorePath(trustStoreFile.getAbsolutePath());
        sslContextFactory.setTrustStorePassword(trustStorePassword);
        sslContextFactory.setNeedClientAuth(isClientAuthNeeded);

        HttpConfiguration https_config = new HttpConfiguration();
        https_config.setSendServerVersion(false);
        https_config.setRequestHeaderSize(512 * 1024);
        https_config.setResponseHeaderSize(512 * 1024);

        SecureRequestCustomizer src = new SecureRequestCustomizer();
        https_config.addCustomizer(src);

        return new ServerConnector(server, sslContextFactory, new HttpConnectionFactory(https_config));
    }

    @Override
    public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException, ServletException {
        res.setContentType("text/html");
        res.setStatus(HttpServletResponse.SC_OK);
        res.getWriter().println("<h1>Hello World!</h1>");
        res.getWriter().println("session=" + req.getSession(true).getId());
    }
}

  1. I使用jetty启动servlet,并试图连接到本地主机:8080,并出现了上述错误。

然后,我尝试通过其他指南创建其他密钥存储和信任商店,例如,我在我的新Keystore中添加了DNS替代名称,如下所述:https://serverfault.com/questions/488003/keytool-subjectalternativename,但没有任何帮助。

我不知道我的情况出了什么问题,也许更有经验的码头和证书会有所帮助。

非常感谢!

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-12 15:34:52

此消息意味着HTTP客户端的TLS层提供的SNI与密钥存储中的SNI主机不匹配。

要知道SNI本身就有限制:

  • localhost不允许使用
  • IP地址文本(例如:192.168.1.215fe80::3831:400c:dc07:7c40)
  • All SNI HostNames必须在其名称中至少包含一个. (所以不要使用简写主机/域名,使用完全限定的规范主机/域名)

这些限制都在规范中,并且常常是大多数问题的原因,比如您正在经历的事情。

根据您的Java版本,这些SNI限制在Java网络堆栈中被检查得比其他版本的Java更早。(在主机名限制与强制使用. 17+的情况下,Java 11的限制较小)

票数 4
EN

Stack Overflow用户

发布于 2022-01-31 18:20:09

当我在本地运行我的应用程序时,我也面临着同样的问题。由于SNI不允许localhost,所以我在代码中暂时禁用了SNI检查。下面是我为在本地运行应用程序而修改的代码:

代码语言:javascript
复制
SecureRequestCustomizer src = new SecureRequestCustomizer();
src.setSniHostCheck(false);
https_config.addCustomizer(src);

注意:对于PROD版本,SniHostCheck仍然被设置为真对我们。我不建议任何人把它设为假的。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69945173

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档