Core server component of Eclipse Jetty web server providing HTTP server functionality, request handling, and connection management
—
Security and SSL support provides comprehensive HTTPS/TLS encryption, client certificate authentication, security headers, and protocol configuration for secure web applications.
The SslConnectionFactory enables SSL/TLS encryption for HTTP connections.
public class SslConnectionFactory extends AbstractConnectionFactory
implements ConnectionFactory.Detecting, ConnectionFactory.Configuring {
// Constructors
public SslConnectionFactory();
public SslConnectionFactory(String nextProtocol);
public SslConnectionFactory(SslContextFactory.Server sslContextFactory, String nextProtocol);
// SSL Context Factory
public SslContextFactory.Server getSslContextFactory();
public void setSslContextFactory(SslContextFactory.Server sslContextFactory);
// Protocol configuration
public String getNextProtocol();
public void setNextProtocol(String nextProtocol);
// Buffer configuration
public boolean isDirectBuffersForEncryption();
public void setDirectBuffersForEncryption(boolean useDirectBuffers);
public boolean isDirectBuffersForDecryption();
public void setDirectBuffersForDecryption(boolean useDirectBuffers);
// Connection creation
public Connection newConnection(Connector connector, EndPoint endPoint);
public EndPoint configure(EndPoint endPoint, Connector connector,
ConnectionMetaData connectionMetaData);
}Server-side SSL context factory for configuring SSL/TLS settings.
public class SslContextFactory.Server extends SslContextFactory {
// Keystore configuration
public void setKeyStorePath(String keyStorePath);
public String getKeyStorePath();
public void setKeyStoreType(String keyStoreType);
public String getKeyStoreType();
public void setKeyStorePassword(String keyStorePassword);
public void setKeyManagerPassword(String keyManagerPassword);
// Truststore configuration
public void setTrustStorePath(String trustStorePath);
public String getTrustStorePath();
public void setTrustStoreType(String trustStoreType);
public String getTrustStoreType();
public void setTrustStorePassword(String trustStorePassword);
// Client authentication
public boolean getWantClientAuth();
public void setWantClientAuth(boolean wantClientAuth);
public boolean getNeedClientAuth();
public void setNeedClientAuth(boolean needClientAuth);
// Protocol configuration
public String[] getIncludeProtocols();
public void setIncludeProtocols(String... protocols);
public String[] getExcludeProtocols();
public void setExcludeProtocols(String... protocols);
// Cipher suite configuration
public String[] getIncludeCipherSuites();
public void setIncludeCipherSuites(String... cipherSuites);
public String[] getExcludeCipherSuites();
public void setExcludeCipherSuites(String... cipherSuites);
// SNI configuration
public boolean isSniRequired();
public void setSniRequired(boolean sniRequired);
public String[] getSniHostCheck();
public void setSniHostCheck(String... hosts);
// Session configuration
public int getSslSessionCacheSize();
public void setSslSessionCacheSize(int sslSessionCacheSize);
public int getSslSessionTimeout();
public void setSslSessionTimeout(int sslSessionTimeout);
// OCSP configuration
public boolean isEnableOCSP();
public void setEnableOCSP(boolean enableOCSP);
public String getOcspResponderURL();
public void setOcspResponderURL(String ocspResponderURL);
}public class BasicHTTPSServer {
public void createHTTPSServer() throws Exception {
Server server = new Server();
// Create SSL context factory
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
// Configure keystore
sslContextFactory.setKeyStorePath("keystore.jks");
sslContextFactory.setKeyStorePassword("keystorepassword");
sslContextFactory.setKeyManagerPassword("keymanagerpassword");
// Create HTTP configuration for HTTPS
HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.setSecureScheme("https");
httpsConfig.setSecurePort(8443);
httpsConfig.addCustomizer(new SecureRequestCustomizer());
// Create HTTPS connector
ServerConnector httpsConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, "http/1.1"),
new HttpConnectionFactory(httpsConfig));
httpsConnector.setPort(8443);
server.addConnector(httpsConnector);
// Set handler
server.setHandler(new SimpleHandler());
server.start();
server.join();
}
}public class AdvancedSSLConfiguration {
public SslContextFactory.Server createSecureSSLContextFactory() {
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
// Keystore configuration
sslContextFactory.setKeyStorePath("conf/keystore.jks");
sslContextFactory.setKeyStorePassword("keystorepassword");
sslContextFactory.setKeyManagerPassword("keypassword");
sslContextFactory.setKeyStoreType("JKS");
// Truststore for client certificates
sslContextFactory.setTrustStorePath("conf/truststore.jks");
sslContextFactory.setTrustStorePassword("truststorepassword");
sslContextFactory.setTrustStoreType("JKS");
// Client certificate authentication
sslContextFactory.setWantClientAuth(true); // Request client cert
sslContextFactory.setNeedClientAuth(false); // Don't require it
// Protocol configuration - only modern TLS versions
sslContextFactory.setIncludeProtocols("TLSv1.2", "TLSv1.3");
sslContextFactory.setExcludeProtocols(
"SSL", "SSLv2", "SSLv3", "TLSv1", "TLSv1.1"
);
// Secure cipher suites only
sslContextFactory.setIncludeCipherSuites(
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
"TLS_AES_256_GCM_SHA384",
"TLS_CHACHA20_POLY1305_SHA256",
"TLS_AES_128_GCM_SHA256"
);
// Exclude weak cipher suites
sslContextFactory.setExcludeCipherSuites(
".*NULL.*", ".*RC4.*", ".*MD5.*", ".*DES.*", ".*DSS.*"
);
// SNI configuration
sslContextFactory.setSniRequired(false);
sslContextFactory.setSniHostCheck("example.com", "*.example.com");
// Session configuration
sslContextFactory.setSslSessionCacheSize(1000);
sslContextFactory.setSslSessionTimeout(3600); // 1 hour
// OCSP stapling
sslContextFactory.setEnableOCSP(true);
// Additional security settings
sslContextFactory.setRenegotiationAllowed(false);
return sslContextFactory;
}
public void setupHTTPSWithClientAuth(Server server) {
SslContextFactory.Server sslContextFactory = createSecureSSLContextFactory();
// Require client certificates
sslContextFactory.setNeedClientAuth(true);
// HTTP configuration with secure customizer
HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.setSecureScheme("https");
httpsConfig.setSecurePort(8443);
SecureRequestCustomizer secureCustomizer = new SecureRequestCustomizer();
secureCustomizer.setStsMaxAge(31536000); // 1 year HSTS
secureCustomizer.setStsIncludeSubDomains(true); // Include subdomains
httpsConfig.addCustomizer(secureCustomizer);
// Create HTTPS connector
ServerConnector httpsConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, "http/1.1"),
new HttpConnectionFactory(httpsConfig));
httpsConnector.setPort(8443);
server.addConnector(httpsConnector);
}
}Customizer that adds security features to HTTPS requests.
public class SecureRequestCustomizer implements HttpConfiguration.Customizer {
// HSTS (HTTP Strict Transport Security) configuration
public long getStsMaxAge();
public void setStsMaxAge(long stsMaxAge);
public boolean isStsIncludeSubDomains();
public void setStsIncludeSubDomains(boolean stsIncludeSubDomains);
// SNI (Server Name Indication) configuration
public boolean isSniRequired();
public void setSniRequired(boolean sniRequired);
public boolean isSniHostCheck();
public void setSniHostCheck(boolean sniHostCheck);
// Request customization
public Request customize(Request request, HttpConfiguration configuration);
}public class SecurityHeadersHandler extends Handler.Wrapper {
private final Map<String, String> securityHeaders;
public SecurityHeadersHandler() {
this.securityHeaders = new HashMap<>();
// Default security headers
securityHeaders.put("X-Content-Type-Options", "nosniff");
securityHeaders.put("X-Frame-Options", "DENY");
securityHeaders.put("X-XSS-Protection", "1; mode=block");
securityHeaders.put("Referrer-Policy", "strict-origin-when-cross-origin");
securityHeaders.put("Content-Security-Policy",
"default-src 'self'; script-src 'self' 'unsafe-inline'; " +
"style-src 'self' 'unsafe-inline'; img-src 'self' data:");
securityHeaders.put("Permissions-Policy",
"geolocation=(), microphone=(), camera=()");
}
public void setSecurityHeader(String name, String value) {
securityHeaders.put(name, value);
}
public void removeSecurityHeader(String name) {
securityHeaders.remove(name);
}
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
// Add security headers to response
for (Map.Entry<String, String> header : securityHeaders.entrySet()) {
response.getHeaders().put(header.getKey(), header.getValue());
}
return super.handle(request, response, callback);
}
}public class HSTSHandler extends Handler.Wrapper {
private final long maxAge;
private final boolean includeSubDomains;
private final boolean preload;
public HSTSHandler(long maxAge, boolean includeSubDomains, boolean preload) {
this.maxAge = maxAge;
this.includeSubDomains = includeSubDomains;
this.preload = preload;
}
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
// Only add HSTS header for HTTPS requests
if (request.getConnectionMetaData().isSecure()) {
StringBuilder hsts = new StringBuilder();
hsts.append("max-age=").append(maxAge);
if (includeSubDomains) {
hsts.append("; includeSubDomains");
}
if (preload) {
hsts.append("; preload");
}
response.getHeaders().put("Strict-Transport-Security", hsts.toString());
}
return super.handle(request, response, callback);
}
}public class ClientCertificateHandler extends Handler.Abstract {
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
// Check if connection is secure
if (!request.getConnectionMetaData().isSecure()) {
sendError(response, callback, 403, "HTTPS required");
return true;
}
// Get client certificates
X509Certificate[] clientCerts = request.getConnectionMetaData().getPeerCertificates();
if (clientCerts == null || clientCerts.length == 0) {
sendError(response, callback, 401, "Client certificate required");
return true;
}
// Validate client certificate
X509Certificate clientCert = clientCerts[0];
if (!isValidClientCertificate(clientCert)) {
sendError(response, callback, 403, "Invalid client certificate");
return true;
}
// Extract user information from certificate
String userDN = clientCert.getSubjectX500Principal().getName();
String commonName = extractCommonName(userDN);
// Set authenticated user in request
request.setAttribute("authenticatedUser", commonName);
request.setAttribute("clientCertificate", clientCert);
// Generate success response
response.setStatus(200);
response.getHeaders().put("Content-Type", "application/json");
String json = String.format(
"{\"authenticated\": true, \"user\": \"%s\", \"subject\": \"%s\"}",
commonName, userDN);
response.write(true, ByteBuffer.wrap(json.getBytes()), callback);
return true;
}
private boolean isValidClientCertificate(X509Certificate cert) {
try {
// Check certificate validity period
cert.checkValidity();
// Check certificate issuer (example)
String issuer = cert.getIssuerX500Principal().getName();
if (!issuer.contains("CN=My CA")) {
return false;
}
// Additional validation logic...
return true;
} catch (Exception e) {
return false;
}
}
private String extractCommonName(String dn) {
// Extract CN from distinguished name
String[] parts = dn.split(",");
for (String part : parts) {
String trimmed = part.trim();
if (trimmed.startsWith("CN=")) {
return trimmed.substring(3);
}
}
return "Unknown";
}
private void sendError(Response response, Callback callback, int status, String message) {
response.setStatus(status);
response.getHeaders().put("Content-Type", "text/plain");
response.write(true, ByteBuffer.wrap(message.getBytes()), callback);
}
}public class HTTPSRedirectHandler extends Handler.Abstract {
private final int httpsPort;
public HTTPSRedirectHandler(int httpsPort) {
this.httpsPort = httpsPort;
}
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
// Check if request is already HTTPS
if (request.getConnectionMetaData().isSecure()) {
return false; // Let next handler process
}
// Build HTTPS URL
String scheme = "https";
String host = request.getHeaders().get("Host");
if (host == null) {
host = "localhost";
}
// Remove port from host if present
if (host.contains(":")) {
host = host.substring(0, host.indexOf(":"));
}
String httpsUrl = scheme + "://" + host +
(httpsPort != 443 ? ":" + httpsPort : "") +
request.getHttpURI().getPathQuery();
// Send redirect response
response.setStatus(301); // Permanent redirect
response.getHeaders().put("Location", httpsUrl);
response.getHeaders().put("Connection", "close");
callback.succeeded();
return true;
}
}public class SecureServerSetup {
public Server createSecureServer() throws Exception {
Server server = new Server();
// HTTP connector (redirects to HTTPS)
ServerConnector httpConnector = new ServerConnector(server);
httpConnector.setPort(8080);
server.addConnector(httpConnector);
// HTTPS connector
SslContextFactory.Server sslContextFactory = createSslContextFactory();
HttpConfiguration httpsConfig = createHttpsConfiguration();
ServerConnector httpsConnector = new ServerConnector(server,
new SslConnectionFactory(sslContextFactory, "http/1.1"),
new HttpConnectionFactory(httpsConfig));
httpsConnector.setPort(8443);
server.addConnector(httpsConnector);
// Create handler chain with security
Handler securityChain = createSecurityHandlerChain();
server.setHandler(securityChain);
return server;
}
private SslContextFactory.Server createSslContextFactory() {
SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
// SSL configuration
sslContextFactory.setKeyStorePath("conf/keystore.jks");
sslContextFactory.setKeyStorePassword("password");
sslContextFactory.setTrustStorePath("conf/truststore.jks");
sslContextFactory.setTrustStorePassword("password");
// Security settings
sslContextFactory.setIncludeProtocols("TLSv1.2", "TLSv1.3");
sslContextFactory.setExcludeProtocols("SSLv3", "TLSv1", "TLSv1.1");
sslContextFactory.setIncludeCipherSuites(
"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"
);
// Client certificate support
sslContextFactory.setWantClientAuth(true);
return sslContextFactory;
}
private HttpConfiguration createHttpsConfiguration() {
HttpConfiguration httpsConfig = new HttpConfiguration();
httpsConfig.setSecureScheme("https");
httpsConfig.setSecurePort(8443);
// Add secure request customizer
SecureRequestCustomizer secureCustomizer = new SecureRequestCustomizer();
secureCustomizer.setStsMaxAge(31536000); // 1 year HSTS
secureCustomizer.setStsIncludeSubDomains(true); // Include subdomains
httpsConfig.addCustomizer(secureCustomizer);
return httpsConfig;
}
private Handler createSecurityHandlerChain() {
// HTTPS redirect handler
HTTPSRedirectHandler httpsRedirect = new HTTPSRedirectHandler(8443);
// Security headers handler
SecurityHeadersHandler securityHeaders = new SecurityHeadersHandler();
// HSTS handler
HSTSHandler hstsHandler = new HSTSHandler(31536000, true, false);
// Client certificate authentication (optional)
ClientCertificateHandler clientCertAuth = new ClientCertificateHandler();
// Application handler
Handler applicationHandler = new MyApplicationHandler();
// Chain handlers together
httpsRedirect.setHandler(securityHeaders);
securityHeaders.setHandler(hstsHandler);
hstsHandler.setHandler(clientCertAuth);
clientCertAuth.setHandler(applicationHandler);
return httpsRedirect;
}
}public class SSLMonitoringHandler extends Handler.Wrapper {
@Override
public boolean handle(Request request, Response response, Callback callback)
throws Exception {
ConnectionMetaData connMeta = request.getConnectionMetaData();
if (connMeta.isSecure()) {
logSSLInfo(request);
}
return super.handle(request, response, callback);
}
private void logSSLInfo(Request request) {
ConnectionMetaData connMeta = request.getConnectionMetaData();
System.out.println("SSL Connection Info:");
System.out.println(" Protocol: " + connMeta.getProtocol());
System.out.println(" Secure: " + connMeta.isSecure());
// Client certificate info
X509Certificate[] clientCerts = connMeta.getPeerCertificates();
if (clientCerts != null && clientCerts.length > 0) {
X509Certificate clientCert = clientCerts[0];
System.out.println(" Client Certificate:");
System.out.println(" Subject: " + clientCert.getSubjectX500Principal().getName());
System.out.println(" Issuer: " + clientCert.getIssuerX500Principal().getName());
System.out.println(" Serial: " + clientCert.getSerialNumber());
} else {
System.out.println(" No client certificate");
}
}
}Install with Tessl CLI
npx tessl i tessl/maven-org-eclipse-jetty--jetty-server