我想用 Java 启动 Apache HTTP 服务器。
过了一会儿我找到了this answer .并按照那里的指示做了。KeyStore
是根据这个 instruction 创建的.
我现在的代码:
import me.project.Main;
import org.apache.http.ExceptionLogger;
import org.apache.http.config.SocketConfig;
import org.apache.http.impl.bootstrap.HttpServer;
import org.apache.http.impl.bootstrap.ServerBootstrap;
import org.apache.http.ssl.SSLContexts;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.net.URL;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
public class Server {
private static final Logger logger = LoggerFactory.getLogger(Server.class);
private static HttpServer server;
public static void createAndStart() {
if (server != null) return;
SSLContext sslContext = prepareSSLContext();
SocketConfig config = SocketConfig.custom().setSoTimeout(1500).setTcpNoDelay(true).build();
server = ServerBootstrap.bootstrap()
.setListenerPort(43286)
.setServerInfo("Test")
.setSocketConfig(config)
.setSslContext(sslContext)
.setExceptionLogger(ExceptionLogger.STD_ERR)
.registerHandler("/", new HelloPage())
.create();
System.out.println("Ok");
try {
server.start();
} catch (IOException ioException) {
logger.error("Cannot start server: ", ioException);
}
}
private static SSLContext prepareSSLContext() {
URL keyStoreFile = Main.class.getClassLoader().getResource("keystore.jks");
if (keyStoreFile == null) {
logger.error("Key store not found");
System.exit(1);
}
SSLContext sslContext = null;
try {
sslContext = SSLContexts.custom()
.loadKeyMaterial(keyStoreFile, "mysuperpass".toCharArray(), "mysuperpass".toCharArray()).build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException | UnrecoverableKeyException | CertificateException | IOException e) {
logger.error("Cannot init ssl context", e);
}
return sslContext;
}
}
它成功启动并打印“Ok”。但是有几点我还是不明白:
loadKeyMaterial (keyStore, storePass, KeyPass)
如何方法知道在没有 key 别名的情况下从商店中获取哪个 key ? 我发现了另一个启用 TLS 的示例 here ,但我不明白在哪里使用对象
conn
后:DefaultBHttpClientConnection conn = new DefaultBHttpClientConnection(8 * 1204);
conn.bind(socket);
对不起,我不太懂英文,用谷歌翻译翻译了这个
最佳答案
It seems to me that this is still SSL protocol, not TLS
这些类最初是在 1990 年代为 SSL(v3) 实现的,但它们从大约 2000 年开始实现 TLS(首先是 1.0,后来是 1.1 1.2,现在是 1.3),而名称保持不变以保持兼容性。事实上,自 2014 年的 8u31 以来,JVM 配置中默认禁用 SSLv3,因为它被 "POODLE" attack 破坏了。而“SSL”类实际上只提供 TLS。
How can I make sure that the server really communicates using the encrypted TLS protocol (except to intercept traffic and watch)
尝试使用 TLS 和非 TLS 工具连接到它。
How does the
loadKeyMaterial (keyStore, storePass, KeyPass)
method know which key to take from the store without the key alias?
它使用 JSSE-default
KeyManager
实现chooseServerAlias
返回第一个 key 和证书条目(即 PrivateKeyEntry
),它发现它适用于启用客户端的密码套件 - 或适用于不再在密码套件中的 TLS 1.3,即启用客户端的 sigalg。 IIRC“第一”是哈希图定义的顺序,这意味着出于实际/人类目的,它是任意的。但是大多数服务器使用一个只包含一个 PrivateKeyEntry 的 keystore ,因此所有选择序列都是相同的。
关于java - Apache 服务器上的 TLS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65306951/