Skip to content

HTTPS / TLS

ACE Framework 通过 ace-httptlsFromPemFiles() 函数与 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
SM2Cangjie 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 通过环境变量或密钥管理服务注入,勿写入配置文件

基于 Apache-2.0 许可证发布