aardio 文档
aardio 范例: ACME 申请证书
阿里云 DNS 解析 | IIS 管理接口
/*
IIS / FastCGI 运行 aardio 可支持 HTTPS。
如果是 aardio 内置的 wsock.tcp.simpleHttpServer 等仅支持 HTTP,
可使用 dotNet 库调用 C# 将 HTTPS 转发到 aardio 的 HTTP 服务器即可,要不了几句代码。
IIS 管理接口: https://www.aardio.com/zh-cn/doc/example/Languages/dotNet/Apps/IIS.html
*/
import console.int;
import web.acme;
import crypt.rsa;
import crypt.cert;
console.showLoading("正在初始化");
// 使用测试环境(开发时推荐)
var acme,err = web.acme("letsencrypt_test");
// 2. 生成或加载账户密钥
acme.initAccountKey(io.appData("/aardio/example/web/acme/account.key"));
// 3. 注册账户,邮箱仅用于接收通知所以不用验证
var account, err = acme.register("admin@aardio.com");
if(!account) {
return console.error("注册失败:", err);
}
console.log("账户 URL:", acme.accountUrl);
// 4. 创建订单
var order, err = acme.newOrder("test-acme.aardio.com");
if(!order) return console.error("创建订单失败:", err);
console.log("订单状态:", order.status);
// 5. 处理授权
for(i, authUrl in order.authorizations){
var auth = acme.getAuthorization(authUrl);
console.log("域名:", auth.identifier.value);
// 查找 HTTP-01 挑战
for(_, challenge in auth.challenges){
if(challenge.type == "http-01"){
var keyAuth = acme.getKeyAuthorization(challenge.token);
console.log("HTTP-01 挑战:");
console.log(" URL: http://" + auth.identifier.value +
"/.well-known/acme-challenge/" + challenge.token);
console.log(" 内容:", keyAuth);
// TODO: 在 Web 服务器上部署挑战文件
console.pause(,"部署完成后按回车继续...");
console.showLoading("正在验证")
// 通知服务器验证
acme.respondChallenge(challenge.url);
// 等待验证完成
var result = acme.pollStatus(authUrl, "valid", 30, 3000);
if(!result) return console.log("验证失败");
console.log("验证通过!");
}
/***************
elseif(challenge.type == "dns-01"){
dnsChallengeFound = true;
// 计算需要的 TXT 记录值
var dnsValue = acme.getDns01Value(challenge.token);
var hostRecord = "_acme-challenge";
// 如果是泛域名或子域名,显示完整主机头有助于理解
var fullRecord = "_acme-challenge." + auth.identifier.value;
//阿里云 DNS 解析: https://www.aardio.com/zh-cn/doc/example/Web/REST/aliyun/dns.html
console.log("----------------------------------------------------");
console.log("【请手动添加 DNS TXT 记录以完成验证】");
console.log("域名(Host):", hostRecord);
console.log("完整记录名:", fullRecord);
console.log("记录值(Value):", dnsValue);
console.log("----------------------------------------------------");
// 暂停等待用户操作
// 在实际工程中,这里可以调用阿里云/腾讯云 API 自动添加解析记录
console.log("请前往域名服务商添加上述 TXT 记录。");
console.log("注意:添加后通常需要等待几分钟让 DNS 全球生效。");
console.pause(, "添加并等待生效后,请按任意键继续验证...");
console.showLoading("正在验证")
console.log("正在通知服务器验证...");
acme.respondChallenge(challenge.url);
// 轮询等待验证结果
var result, err = acme.pollStatus(authUrl, "valid", 30, 5000);
if(!result) {
console.error("验证失败:", err);
return;
}
console.log("域名验证通过!");
}
***************/
}
}
console.log("正在申请证书")
// 6. 生成域名密钥和 CSR
import crypt.csr;
var csrGen = crypt.csr();
csrGen.genSignatureKey(2048) // 生成密钥对
var domainKeyPem = csrGen.exportPrivateKeyPkcs8ToPem();
string.save("/domain.key",domainKeyPem)
var csrDer, err = csrGen.createDer("test-acme.aardio.com");
csrGen.delete();
// 7. 完成订单
var result = acme.finalizeOrder(order.finalize, csrDer);
console.log("Finalize 状态:", result.status);
console.showLoading("正在签发证书")
// 8. 等待证书签发
order = acme.pollStatus(order.orderUrl, "valid", 30, 3000);
if(!order) return console.log("证书签发失败");
// 9. 下载证书
var certPem = acme.downloadCertificate(order.certificate);
if(!certPem) return console.error("下载证书内容为空");
string.save("/cert.pem", certPem);
console.log("已保存 cert.pem 证书!");
// 从 PEM 创建证书对象
import crypt.cert
var crt, err = crypt.cert.fromPem(domainKeyPem, certPem);
//显示证书信息
console.log(" 主题:", crt.subject);
console.log(" 颁发者:", crt.issuer);
console.log(" 序列号:", crt.serialNumber);
console.log(" 指纹:", crt.thumbprint);
console.log(" 算法:", crt.algorithm);
console.log(" 生效时间:", crt.validFrom);
console.log(" 过期时间:", crt.validTo);
console.log(" 是否有效:", crt.isValid);
console.log(" 含私钥:", crt.hasPrivateKey);
//转换为 pfx 文件
var pfxPath, password = crt.exportPfx("123456", "/cert.pfx");
if(pfxPath){
console.success("PFX 转换成功!已保存为:", pfxPath);
console.log("密码:", password);
} else {
// 导出失败时,第二个返回值是错误信息
console.error("PFX 导出失败:", password);
}
console.pause();
Markdown 格式