前言
随着Let’s Encrypt证书的不断流行,大多数网站都开始使用其作为自己的证书。当然,最主要的还是它的申请流程简单且免费!
搜了很久也没找到可以用的,大部分文章都已过时,官方文档也太过简略,无奈只能看源码总结出了部分实现代码,已经尽力把注释写的很详细了。
代码
- 使用nodejs实现
- 使用greenlock npm包
- 使用https方式验证
- 以申请域名 xpengp.test.com 域名为例
'use strict';
const pkg = require('./package.json'); // 引入项目配置文件
const Greenlock = require('greenlock');
const path = require('path');
const greenlock = Greenlock.create({
packageRoot: path.resolve(__dirname, './lets'), // 后面config,store,account,live 的根目录(若后面配置的是绝对路径,当然就不会受影响了)
configDir: './config.json', // config.json文件目录
maintainerEmail: 'youremail', // 申请证书所需邮箱(默认邮箱 但必须有)
packageAgent: pkg.name + '/' + pkg.version, // 申请证书请求中的User-Agent字段 name不能是汉字(package.json项目名称不支持汉字)
staging: true, // 是否使用测试环境 测试环境会有更多的错误申请次数
notify: function (event, details) { // 错误回调
if ('error' === event) {
console.error('出错了:');
console.error(details);
}
}
});
//设置默认参数
greenlock.manager
.defaults({ // 设置以后添加域名时的默认参数
agreeToTerms: true, // 同意申请协议
subscriberEmail: 'youremail', // 默认邮箱 可在添加时重写此配置
// challenges: { // 自动生成的测试文件目录 可以再这里默认配置 也可以在添加时配置或重写
// "http-01": {
// module: "acme-http-01-webroot",
// webroot: "/www/wwwroot/:hostname/.well-known/acme-challenge" // :hostname 并没有什么作用 但在store.basePath中起作用
// }
// },
store: {
module: 'greenlock-store-fs',
basePath: '/root/letsencrypt' // 申请的密钥目录 申请的证书默认会放在这里的live目录下 (为相对路径时 以packageRoot为根目录)
}
})
.then(function (fullConfig) { // 设置默认参数后的成功回调
console.log('初始化完成')
});
// add domains
greenlock.add({ // 新增域名并自动申请证书
subject: 'xpengp.test.com', // subject会用于其他地方创建目录名时 使用
altnames: ['xpengp.test.com'], // 可以为多个 但第一个必须和subject相同
challenges: { // 重写默认测试地址
"http-01": { // 采用http方式申请 方便
module: "acme-http-01-webroot",
webroot: "/www/wwwroot/xpengp.test.com/.well-known/acme-challenge" // 该目录保存申请证书时的challenge文件 具体看下面注释
}
},
});
// 获取证书 可用于测试是否申请成功 返回promise
greenlock
.get({ servername: 'xpengp.test.com' }) // 申请证书成功后 使用此方法可获取证书的所有信息
.then(function (pems) { // 成功回调
console.log(pems);
})
.catch(function (e) {
console.error('Big bad error:', e.code);
console.error(e);//
});
(async ()=> {
let ret = await greenlock.get({ servername: 'xpengp.test.com' });
console.log(ret);
})();
// 自动续签检查更新(调用后会在后台运行并自动续签)
greenlock.renew({}).then(function(results) {
// 检查完的回调
results.forEach(function(site) {
if (site.error) {
console.error(site.subject, site.error);
return;
}
console.log('Renewed certificate for', site.subject, site.altnames);
});
});
// 函数描述
/*
* 1.使用Greenlock.create 创建使用Greenlock对象
* 2.greenlock.manager.defaults 设置后面添加域名的默认参数 可在添加时重写部分参数
* 3.greenlock.add 添加域名
* 4.greenlock.get获取域名的证书信息
* */
// let's 的证书申请流程(个人理解)
/*
* 1.使用该库构建acount信息 生成对应邮箱的公钥等信息 存放在store设置的目录下
* 2.申请时 会在本地自动创建challenge文件 存放在challenges.http-01.webroot设置的目录下
* 3.采用http验证方式 - 在发出申请请求时附带token let's服务器会根据token获取域名 .well-known/acme-challenge 目录下的对应文件 并比较是否相同 若相同即验证成功
* 4.验证成功后 会自动删除challenge文件
* 5.会在 store设置的根目录下创建live目录 然后对应域名 分别存放证书信息
* 6.之后 会根据config配置 自动检查并更新证书
* */
总结
- Let's发送的GET测试请求路径一般是固定的(.well-known/acme-challenge),所以可以把 .well-known 路径固定代理到一个文件夹来进行申请证书使用。如果自己项目中可能会用到这个路径,那只能在申请前先注释掉相应的代理了。
- 当然申请证书也是有次数限制的,尤其要注意账户申请次数和申请失败次数,所以建议先试用测试环境(不会避免限制,但可以增加次数)来测试申请证书。
Let's速率限制(官方):https://letsencrypt.org/zh-cn/docs/rate-limits/ - 如果你的域名是解析到负载的,要对应多个ip。由于负载均衡,申请成功的概率会相应降低。