or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdconnection-management.mdcontext-resources.mdhandlers.mdindex.mdrequest-logging.mdrequest-response.mdsecurity-ssl.mdserver-core.mdsession-management.mdutility-handlers.md

security-ssl.mddocs/

0

# Security and SSL

1

2

Security and SSL support provides comprehensive HTTPS/TLS encryption, client certificate authentication, security headers, and protocol configuration for secure web applications.

3

4

## SSL Connection Factory

5

6

The `SslConnectionFactory` enables SSL/TLS encryption for HTTP connections.

7

8

```java { .api }

9

public class SslConnectionFactory extends AbstractConnectionFactory

10

implements ConnectionFactory.Detecting, ConnectionFactory.Configuring {

11

12

// Constructors

13

public SslConnectionFactory();

14

public SslConnectionFactory(String nextProtocol);

15

public SslConnectionFactory(SslContextFactory.Server sslContextFactory, String nextProtocol);

16

17

// SSL Context Factory

18

public SslContextFactory.Server getSslContextFactory();

19

public void setSslContextFactory(SslContextFactory.Server sslContextFactory);

20

21

// Protocol configuration

22

public String getNextProtocol();

23

public void setNextProtocol(String nextProtocol);

24

25

// Buffer configuration

26

public boolean isDirectBuffersForEncryption();

27

public void setDirectBuffersForEncryption(boolean useDirectBuffers);

28

public boolean isDirectBuffersForDecryption();

29

public void setDirectBuffersForDecryption(boolean useDirectBuffers);

30

31

// Connection creation

32

public Connection newConnection(Connector connector, EndPoint endPoint);

33

public EndPoint configure(EndPoint endPoint, Connector connector,

34

ConnectionMetaData connectionMetaData);

35

}

36

```

37

38

## SslContextFactory.Server

39

40

Server-side SSL context factory for configuring SSL/TLS settings.

41

42

```java { .api }

43

public class SslContextFactory.Server extends SslContextFactory {

44

// Keystore configuration

45

public void setKeyStorePath(String keyStorePath);

46

public String getKeyStorePath();

47

public void setKeyStoreType(String keyStoreType);

48

public String getKeyStoreType();

49

public void setKeyStorePassword(String keyStorePassword);

50

public void setKeyManagerPassword(String keyManagerPassword);

51

52

// Truststore configuration

53

public void setTrustStorePath(String trustStorePath);

54

public String getTrustStorePath();

55

public void setTrustStoreType(String trustStoreType);

56

public String getTrustStoreType();

57

public void setTrustStorePassword(String trustStorePassword);

58

59

// Client authentication

60

public boolean getWantClientAuth();

61

public void setWantClientAuth(boolean wantClientAuth);

62

public boolean getNeedClientAuth();

63

public void setNeedClientAuth(boolean needClientAuth);

64

65

// Protocol configuration

66

public String[] getIncludeProtocols();

67

public void setIncludeProtocols(String... protocols);

68

public String[] getExcludeProtocols();

69

public void setExcludeProtocols(String... protocols);

70

71

// Cipher suite configuration

72

public String[] getIncludeCipherSuites();

73

public void setIncludeCipherSuites(String... cipherSuites);

74

public String[] getExcludeCipherSuites();

75

public void setExcludeCipherSuites(String... cipherSuites);

76

77

// SNI configuration

78

public boolean isSniRequired();

79

public void setSniRequired(boolean sniRequired);

80

public String[] getSniHostCheck();

81

public void setSniHostCheck(String... hosts);

82

83

// Session configuration

84

public int getSslSessionCacheSize();

85

public void setSslSessionCacheSize(int sslSessionCacheSize);

86

public int getSslSessionTimeout();

87

public void setSslSessionTimeout(int sslSessionTimeout);

88

89

// OCSP configuration

90

public boolean isEnableOCSP();

91

public void setEnableOCSP(boolean enableOCSP);

92

public String getOcspResponderURL();

93

public void setOcspResponderURL(String ocspResponderURL);

94

}

95

```

96

97

## Basic HTTPS Setup

98

99

```java

100

public class BasicHTTPSServer {

101

102

public void createHTTPSServer() throws Exception {

103

Server server = new Server();

104

105

// Create SSL context factory

106

SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();

107

108

// Configure keystore

109

sslContextFactory.setKeyStorePath("keystore.jks");

110

sslContextFactory.setKeyStorePassword("keystorepassword");

111

sslContextFactory.setKeyManagerPassword("keymanagerpassword");

112

113

// Create HTTP configuration for HTTPS

114

HttpConfiguration httpsConfig = new HttpConfiguration();

115

httpsConfig.setSecureScheme("https");

116

httpsConfig.setSecurePort(8443);

117

httpsConfig.addCustomizer(new SecureRequestCustomizer());

118

119

// Create HTTPS connector

120

ServerConnector httpsConnector = new ServerConnector(server,

121

new SslConnectionFactory(sslContextFactory, "http/1.1"),

122

new HttpConnectionFactory(httpsConfig));

123

httpsConnector.setPort(8443);

124

125

server.addConnector(httpsConnector);

126

127

// Set handler

128

server.setHandler(new SimpleHandler());

129

130

server.start();

131

server.join();

132

}

133

}

134

```

135

136

## Advanced SSL Configuration

137

138

```java

139

public class AdvancedSSLConfiguration {

140

141

public SslContextFactory.Server createSecureSSLContextFactory() {

142

SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();

143

144

// Keystore configuration

145

sslContextFactory.setKeyStorePath("conf/keystore.jks");

146

sslContextFactory.setKeyStorePassword("keystorepassword");

147

sslContextFactory.setKeyManagerPassword("keypassword");

148

sslContextFactory.setKeyStoreType("JKS");

149

150

// Truststore for client certificates

151

sslContextFactory.setTrustStorePath("conf/truststore.jks");

152

sslContextFactory.setTrustStorePassword("truststorepassword");

153

sslContextFactory.setTrustStoreType("JKS");

154

155

// Client certificate authentication

156

sslContextFactory.setWantClientAuth(true); // Request client cert

157

sslContextFactory.setNeedClientAuth(false); // Don't require it

158

159

// Protocol configuration - only modern TLS versions

160

sslContextFactory.setIncludeProtocols("TLSv1.2", "TLSv1.3");

161

sslContextFactory.setExcludeProtocols(

162

"SSL", "SSLv2", "SSLv3", "TLSv1", "TLSv1.1"

163

);

164

165

// Secure cipher suites only

166

sslContextFactory.setIncludeCipherSuites(

167

"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",

168

"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",

169

"TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",

170

"TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",

171

"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",

172

"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",

173

"TLS_AES_256_GCM_SHA384",

174

"TLS_CHACHA20_POLY1305_SHA256",

175

"TLS_AES_128_GCM_SHA256"

176

);

177

178

// Exclude weak cipher suites

179

sslContextFactory.setExcludeCipherSuites(

180

".*NULL.*", ".*RC4.*", ".*MD5.*", ".*DES.*", ".*DSS.*"

181

);

182

183

// SNI configuration

184

sslContextFactory.setSniRequired(false);

185

sslContextFactory.setSniHostCheck("example.com", "*.example.com");

186

187

// Session configuration

188

sslContextFactory.setSslSessionCacheSize(1000);

189

sslContextFactory.setSslSessionTimeout(3600); // 1 hour

190

191

// OCSP stapling

192

sslContextFactory.setEnableOCSP(true);

193

194

// Additional security settings

195

sslContextFactory.setRenegotiationAllowed(false);

196

197

return sslContextFactory;

198

}

199

200

public void setupHTTPSWithClientAuth(Server server) {

201

SslContextFactory.Server sslContextFactory = createSecureSSLContextFactory();

202

203

// Require client certificates

204

sslContextFactory.setNeedClientAuth(true);

205

206

// HTTP configuration with secure customizer

207

HttpConfiguration httpsConfig = new HttpConfiguration();

208

httpsConfig.setSecureScheme("https");

209

httpsConfig.setSecurePort(8443);

210

211

SecureRequestCustomizer secureCustomizer = new SecureRequestCustomizer();

212

secureCustomizer.setStsMaxAge(31536000); // 1 year HSTS

213

secureCustomizer.setStsIncludeSubDomains(true); // Include subdomains

214

httpsConfig.addCustomizer(secureCustomizer);

215

216

// Create HTTPS connector

217

ServerConnector httpsConnector = new ServerConnector(server,

218

new SslConnectionFactory(sslContextFactory, "http/1.1"),

219

new HttpConnectionFactory(httpsConfig));

220

httpsConnector.setPort(8443);

221

222

server.addConnector(httpsConnector);

223

}

224

}

225

```

226

227

## SecureRequestCustomizer

228

229

Customizer that adds security features to HTTPS requests.

230

231

```java { .api }

232

public class SecureRequestCustomizer implements HttpConfiguration.Customizer {

233

// HSTS (HTTP Strict Transport Security) configuration

234

public long getStsMaxAge();

235

public void setStsMaxAge(long stsMaxAge);

236

public boolean isStsIncludeSubDomains();

237

public void setStsIncludeSubDomains(boolean stsIncludeSubDomains);

238

239

// SNI (Server Name Indication) configuration

240

public boolean isSniRequired();

241

public void setSniRequired(boolean sniRequired);

242

public boolean isSniHostCheck();

243

public void setSniHostCheck(boolean sniHostCheck);

244

245

// Request customization

246

public Request customize(Request request, HttpConfiguration configuration);

247

}

248

```

249

250

## Security Headers

251

252

### Custom Security Headers Handler

253

254

```java

255

public class SecurityHeadersHandler extends Handler.Wrapper {

256

private final Map<String, String> securityHeaders;

257

258

public SecurityHeadersHandler() {

259

this.securityHeaders = new HashMap<>();

260

261

// Default security headers

262

securityHeaders.put("X-Content-Type-Options", "nosniff");

263

securityHeaders.put("X-Frame-Options", "DENY");

264

securityHeaders.put("X-XSS-Protection", "1; mode=block");

265

securityHeaders.put("Referrer-Policy", "strict-origin-when-cross-origin");

266

securityHeaders.put("Content-Security-Policy",

267

"default-src 'self'; script-src 'self' 'unsafe-inline'; " +

268

"style-src 'self' 'unsafe-inline'; img-src 'self' data:");

269

securityHeaders.put("Permissions-Policy",

270

"geolocation=(), microphone=(), camera=()");

271

}

272

273

public void setSecurityHeader(String name, String value) {

274

securityHeaders.put(name, value);

275

}

276

277

public void removeSecurityHeader(String name) {

278

securityHeaders.remove(name);

279

}

280

281

@Override

282

public boolean handle(Request request, Response response, Callback callback)

283

throws Exception {

284

285

// Add security headers to response

286

for (Map.Entry<String, String> header : securityHeaders.entrySet()) {

287

response.getHeaders().put(header.getKey(), header.getValue());

288

}

289

290

return super.handle(request, response, callback);

291

}

292

}

293

```

294

295

### HSTS Handler

296

297

```java

298

public class HSTSHandler extends Handler.Wrapper {

299

private final long maxAge;

300

private final boolean includeSubDomains;

301

private final boolean preload;

302

303

public HSTSHandler(long maxAge, boolean includeSubDomains, boolean preload) {

304

this.maxAge = maxAge;

305

this.includeSubDomains = includeSubDomains;

306

this.preload = preload;

307

}

308

309

@Override

310

public boolean handle(Request request, Response response, Callback callback)

311

throws Exception {

312

313

// Only add HSTS header for HTTPS requests

314

if (request.getConnectionMetaData().isSecure()) {

315

StringBuilder hsts = new StringBuilder();

316

hsts.append("max-age=").append(maxAge);

317

318

if (includeSubDomains) {

319

hsts.append("; includeSubDomains");

320

}

321

322

if (preload) {

323

hsts.append("; preload");

324

}

325

326

response.getHeaders().put("Strict-Transport-Security", hsts.toString());

327

}

328

329

return super.handle(request, response, callback);

330

}

331

}

332

```

333

334

## Client Certificate Authentication

335

336

```java

337

public class ClientCertificateHandler extends Handler.Abstract {

338

339

@Override

340

public boolean handle(Request request, Response response, Callback callback)

341

throws Exception {

342

343

// Check if connection is secure

344

if (!request.getConnectionMetaData().isSecure()) {

345

sendError(response, callback, 403, "HTTPS required");

346

return true;

347

}

348

349

// Get client certificates

350

X509Certificate[] clientCerts = request.getConnectionMetaData().getPeerCertificates();

351

352

if (clientCerts == null || clientCerts.length == 0) {

353

sendError(response, callback, 401, "Client certificate required");

354

return true;

355

}

356

357

// Validate client certificate

358

X509Certificate clientCert = clientCerts[0];

359

if (!isValidClientCertificate(clientCert)) {

360

sendError(response, callback, 403, "Invalid client certificate");

361

return true;

362

}

363

364

// Extract user information from certificate

365

String userDN = clientCert.getSubjectX500Principal().getName();

366

String commonName = extractCommonName(userDN);

367

368

// Set authenticated user in request

369

request.setAttribute("authenticatedUser", commonName);

370

request.setAttribute("clientCertificate", clientCert);

371

372

// Generate success response

373

response.setStatus(200);

374

response.getHeaders().put("Content-Type", "application/json");

375

376

String json = String.format(

377

"{\"authenticated\": true, \"user\": \"%s\", \"subject\": \"%s\"}",

378

commonName, userDN);

379

380

response.write(true, ByteBuffer.wrap(json.getBytes()), callback);

381

return true;

382

}

383

384

private boolean isValidClientCertificate(X509Certificate cert) {

385

try {

386

// Check certificate validity period

387

cert.checkValidity();

388

389

// Check certificate issuer (example)

390

String issuer = cert.getIssuerX500Principal().getName();

391

if (!issuer.contains("CN=My CA")) {

392

return false;

393

}

394

395

// Additional validation logic...

396

397

return true;

398

} catch (Exception e) {

399

return false;

400

}

401

}

402

403

private String extractCommonName(String dn) {

404

// Extract CN from distinguished name

405

String[] parts = dn.split(",");

406

for (String part : parts) {

407

String trimmed = part.trim();

408

if (trimmed.startsWith("CN=")) {

409

return trimmed.substring(3);

410

}

411

}

412

return "Unknown";

413

}

414

415

private void sendError(Response response, Callback callback, int status, String message) {

416

response.setStatus(status);

417

response.getHeaders().put("Content-Type", "text/plain");

418

response.write(true, ByteBuffer.wrap(message.getBytes()), callback);

419

}

420

}

421

```

422

423

## HTTPS Redirect Handler

424

425

```java

426

public class HTTPSRedirectHandler extends Handler.Abstract {

427

private final int httpsPort;

428

429

public HTTPSRedirectHandler(int httpsPort) {

430

this.httpsPort = httpsPort;

431

}

432

433

@Override

434

public boolean handle(Request request, Response response, Callback callback)

435

throws Exception {

436

437

// Check if request is already HTTPS

438

if (request.getConnectionMetaData().isSecure()) {

439

return false; // Let next handler process

440

}

441

442

// Build HTTPS URL

443

String scheme = "https";

444

String host = request.getHeaders().get("Host");

445

if (host == null) {

446

host = "localhost";

447

}

448

449

// Remove port from host if present

450

if (host.contains(":")) {

451

host = host.substring(0, host.indexOf(":"));

452

}

453

454

String httpsUrl = scheme + "://" + host +

455

(httpsPort != 443 ? ":" + httpsPort : "") +

456

request.getHttpURI().getPathQuery();

457

458

// Send redirect response

459

response.setStatus(301); // Permanent redirect

460

response.getHeaders().put("Location", httpsUrl);

461

response.getHeaders().put("Connection", "close");

462

463

callback.succeeded();

464

return true;

465

}

466

}

467

```

468

469

## Complete Secure Server Setup

470

471

```java

472

public class SecureServerSetup {

473

474

public Server createSecureServer() throws Exception {

475

Server server = new Server();

476

477

// HTTP connector (redirects to HTTPS)

478

ServerConnector httpConnector = new ServerConnector(server);

479

httpConnector.setPort(8080);

480

server.addConnector(httpConnector);

481

482

// HTTPS connector

483

SslContextFactory.Server sslContextFactory = createSslContextFactory();

484

HttpConfiguration httpsConfig = createHttpsConfiguration();

485

486

ServerConnector httpsConnector = new ServerConnector(server,

487

new SslConnectionFactory(sslContextFactory, "http/1.1"),

488

new HttpConnectionFactory(httpsConfig));

489

httpsConnector.setPort(8443);

490

server.addConnector(httpsConnector);

491

492

// Create handler chain with security

493

Handler securityChain = createSecurityHandlerChain();

494

server.setHandler(securityChain);

495

496

return server;

497

}

498

499

private SslContextFactory.Server createSslContextFactory() {

500

SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();

501

502

// SSL configuration

503

sslContextFactory.setKeyStorePath("conf/keystore.jks");

504

sslContextFactory.setKeyStorePassword("password");

505

sslContextFactory.setTrustStorePath("conf/truststore.jks");

506

sslContextFactory.setTrustStorePassword("password");

507

508

// Security settings

509

sslContextFactory.setIncludeProtocols("TLSv1.2", "TLSv1.3");

510

sslContextFactory.setExcludeProtocols("SSLv3", "TLSv1", "TLSv1.1");

511

sslContextFactory.setIncludeCipherSuites(

512

"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",

513

"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256"

514

);

515

516

// Client certificate support

517

sslContextFactory.setWantClientAuth(true);

518

519

return sslContextFactory;

520

}

521

522

private HttpConfiguration createHttpsConfiguration() {

523

HttpConfiguration httpsConfig = new HttpConfiguration();

524

httpsConfig.setSecureScheme("https");

525

httpsConfig.setSecurePort(8443);

526

527

// Add secure request customizer

528

SecureRequestCustomizer secureCustomizer = new SecureRequestCustomizer();

529

secureCustomizer.setStsMaxAge(31536000); // 1 year HSTS

530

secureCustomizer.setStsIncludeSubDomains(true); // Include subdomains

531

httpsConfig.addCustomizer(secureCustomizer);

532

533

return httpsConfig;

534

}

535

536

private Handler createSecurityHandlerChain() {

537

// HTTPS redirect handler

538

HTTPSRedirectHandler httpsRedirect = new HTTPSRedirectHandler(8443);

539

540

// Security headers handler

541

SecurityHeadersHandler securityHeaders = new SecurityHeadersHandler();

542

543

// HSTS handler

544

HSTSHandler hstsHandler = new HSTSHandler(31536000, true, false);

545

546

// Client certificate authentication (optional)

547

ClientCertificateHandler clientCertAuth = new ClientCertificateHandler();

548

549

// Application handler

550

Handler applicationHandler = new MyApplicationHandler();

551

552

// Chain handlers together

553

httpsRedirect.setHandler(securityHeaders);

554

securityHeaders.setHandler(hstsHandler);

555

hstsHandler.setHandler(clientCertAuth);

556

clientCertAuth.setHandler(applicationHandler);

557

558

return httpsRedirect;

559

}

560

}

561

```

562

563

## SSL Debugging and Monitoring

564

565

```java

566

public class SSLMonitoringHandler extends Handler.Wrapper {

567

568

@Override

569

public boolean handle(Request request, Response response, Callback callback)

570

throws Exception {

571

572

ConnectionMetaData connMeta = request.getConnectionMetaData();

573

574

if (connMeta.isSecure()) {

575

logSSLInfo(request);

576

}

577

578

return super.handle(request, response, callback);

579

}

580

581

private void logSSLInfo(Request request) {

582

ConnectionMetaData connMeta = request.getConnectionMetaData();

583

584

System.out.println("SSL Connection Info:");

585

System.out.println(" Protocol: " + connMeta.getProtocol());

586

System.out.println(" Secure: " + connMeta.isSecure());

587

588

// Client certificate info

589

X509Certificate[] clientCerts = connMeta.getPeerCertificates();

590

if (clientCerts != null && clientCerts.length > 0) {

591

X509Certificate clientCert = clientCerts[0];

592

System.out.println(" Client Certificate:");

593

System.out.println(" Subject: " + clientCert.getSubjectX500Principal().getName());

594

System.out.println(" Issuer: " + clientCert.getIssuerX500Principal().getName());

595

System.out.println(" Serial: " + clientCert.getSerialNumber());

596

} else {

597

System.out.println(" No client certificate");

598

}

599

}

600

}

601

```