Coo*_*rSK 9 java https servlets jetty keystore
我正在尝试解决通过 HTTPS 运行的 Jetty servlet 的问题。
它在浏览器中显示此错误页面:
我做了什么:
我按照此处所述创建了密钥库和信任库:如何生成密钥库和信任库
这两个文件都放在我的项目目录中,并编写了代码来加载这些文件。
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());
}
}
Run Code Online (Sandbox Code Playgroud)
然后我尝试通过其他指南创建其他密钥库和信任库,例如,我向新密钥库添加了 DNS 备用名称,如下所述:https: //serverfault.com/questions/488003/keytool-subjectalternativename但没有任何帮助。
我不知道我的情况出了什么问题,也许对码头和证书更有经验的人会有所帮助。
太感谢了!
当我从本地运行应用程序时,我也遇到了同样的问题。由于 SNI 不允许使用 localhost,因此我在代码中暂时禁用了 SNI 检查。以下是我为在本地运行应用程序而修改的代码:
SecureRequestCustomizer src = new SecureRequestCustomizer();
src.setSniHostCheck(false);
https_config.addCustomizer(src);
Run Code Online (Sandbox Code Playgroud)
注意:对于 PROD 版本,SniHostCheck 对我们来说仍然设置为 true。而且我不建议任何人将其设置为 false。
此消息意味着 HTTP 客户端的 TLS 层提供的 SNI 与密钥库中的 SNI 主机之一不匹配。
要知道SNI本身是有限制的:
localhost不允许192.168.1.215或fe80::3831:400c:dc07:7c40).(因此不要使用速记主机/域名,使用完全限定的规范主机/域名)这些限制在规范中,并且通常是大多数问题(例如您遇到的问题)的原因。
根据您的 Java 版本,这些 SNI 限制在 Java 网络堆栈中检查的速度比其他版本的 Java 更快。(Java 11 对.主机名限制的限制比 Java 17+ 的限制要少)
| 归档时间: |
|
| 查看次数: |
17875 次 |
| 最近记录: |