HTTPS / TLS
ACE Framework 通过 ace-http 的 tlsFromPemFiles() 函数与 ListenOptions.tls 字段启用 HTTPS,底层基于 stdx.net.tls,支持 RSA / ECDSA / SM2 证书。
方式一:配置文件驱动(推荐)
在 application.toml 中配置证书路径,AceApplication.run() 自动启用 TLS:
toml
# application.toml
[server]
host = "0.0.0.0"
port = 8443
[server.tls]
cert = "/etc/ssl/certs/server.crt" # 证书链 PEM(叶子在前,CA 在后)
key = "/etc/ssl/private/server.key" # 私钥 PEM
# keyPassword = "changeit" # 可选,加密私钥的口令应用代码无需任何改动:
cangjie
main(): Int64 {
AceApplication.run() // 自动读取 server.tls.cert / server.tls.key
return 0
}服务启动后输出:
ACE serving on https://0.0.0.0:8443 (env=local)方式二:编程式配置
使用 tlsFromPemFiles() 构造 TLS 配置,通过 ListenOptions 传入:
cangjie
import ace_http.*
main(): Int64 {
let app = AceApplication.buildApp()
var opts = ListenOptions()
opts.tls = tlsFromPemFiles("server.crt", "server.key")
listenWith(app, "0.0.0.0", 8443, opts)
return 0
}加密私钥(带口令):
cangjie
opts.tls = tlsFromPemFiles("server.crt", "server.key", "p@ssw0rd")证书格式
证书链 PEM
若使用 CA 签发的证书,cert 文件须包含完整证书链(叶子证书在前,中间 CA 在后):
-----BEGIN CERTIFICATE-----
(你的域名证书)
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
(中间 CA 证书)
-----END CERTIFICATE-----支持的密钥类型
tlsFromPemFiles 使用 GeneralPrivateKey.decodeFromPem 自动识别密钥类型:
| 类型 | PEM 头部 |
|---|---|
| RSA | -----BEGIN RSA PRIVATE KEY----- 或 PKCS#8 |
| ECDSA | -----BEGIN EC PRIVATE KEY----- 或 PKCS#8 |
| SM2 | Cangjie stdx 支持的 SM2 格式 |
自签名证书(开发环境)
bash
# 生成 ECDSA 自签名证书(有效期 365 天)
openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 \
-keyout server.key -out server.crt \
-days 365 -nodes \
-subj "/CN=localhost"开发配置:
toml
# application-local.toml
[server.tls]
cert = "server.crt"
key = "server.key"浏览器访问 https://localhost:8443 需手动信任自签名证书,或使用 curl -k。
连接超时配置
通过 ListenOptions 同时配置 TLS 和超时:
cangjie
var opts = ListenOptions()
opts.tls = tlsFromPemFiles("server.crt", "server.key")
opts.readTimeoutMs = 30000 // 30 秒读取超时
opts.writeTimeoutMs = 30000 // 30 秒写入超时
listenWith(app, "0.0.0.0", 8443, opts)HTTP + HTTPS 双端口
如需同时监听 HTTP(用于重定向)和 HTTPS,启动两个协程:
cangjie
import ace_http.*
import ace_web.*
import std.sync.*
main(): Int64 {
let app = AceApplication.buildApp()
// HTTP 端口:强制重定向到 HTTPS
let redirectApp = App()
redirectApp.use({ctx: Context, _: Next =>
ctx.status = 301
ctx.setHeader("Location", "https://yourdomain.com${ctx.path}")
})
let latch = CountDownLatch(2)
spawn {
listen(redirectApp, "0.0.0.0", 8080)
latch.countDown()
}
spawn {
var opts = ListenOptions()
opts.tls = tlsFromPemFiles("server.crt", "server.key")
listenWith(app, "0.0.0.0", 8443, opts)
latch.countDown()
}
latch.await()
return 0
}反向代理(Let's Encrypt)
生产环境推荐在 Nginx / Caddy 等反向代理处终止 TLS,ACE 服务监听 HTTP:
nginx
# Nginx 配置
server {
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/yourdomain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/yourdomain.com/privkey.pem;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}此场景 ACE 无需配置 TLS,应用代码读取 X-Forwarded-Proto 头判断请求协议。
生产检查清单
- [ ] 证书链完整(叶子证书 + 中间 CA)
- [ ] 私钥权限
chmod 600 server.key - [ ] 证书有效期监控(建议提前 30 天告警)
- [ ] 仅启用 TLS 1.2+(stdx 默认已限制)
- [ ] 生产环境
keyPassword通过环境变量或密钥管理服务注入,勿写入配置文件