❝前言:
之前看到别人做的在线生成安卓证书,只需要填写几个输入框,就能自动下载一个安卓证书,觉得不错,想着能不能自己实现一下,可是一如此门深似海,说多了都是泪!❞
使用的技术
后端技术
部署在linux系统上,后端用的Koa2以及相关的生态,使用Dockerfile构建的自定义镜像。
前端技术
使用的是纯html页面,引入vue3、axios以及element-plus,使用nginx代理网页。
遇到的问题
如何生成证书文件?
经过验证,参考的网站若在一定时间内,多人同时生成证书,只有一人会成功!
这是因为证书是用java的keytool自动生成的,若当前目录已经有一个证书文件,再生成同名的就会报错!
当前的网站可能也会存在这个问题,但进行了显示优化!因为生成的证书名称统一为android.keystore,说避免也可以避免,但是同时访问的人数过多的话依旧比较麻烦,就没做处理,毕竟流量也没那么大。
如何让前端下载文件?
这里没有做到跟参考网站那样!还是比较赞同他的做法,请求响应是空的,浏览器直接下载的,而我的是一个二进制流,需要前端再次处理!
有知道如何实现的,可以告知一下!
如何调用CMD?
使用的是node的子进程child_process的spawn方法,区别在于Windows和非Windows使用不一样
解决思路
使用cmd生成一个证书
判断当前系统
// os模块 内置模块
const os = require('os');
// 当前系统
os.platform
// darwin 是 Mac
// win32和win64 都是 Windows
// linux 是 Linux
调用CMD
// 子进程 内置模块
const spawn = require("child_process").spawn;
// windows 系统
const result = spawn("cmd.exe", ["/s", "/c", cmd , options])
// 非windows 系统
const result = spawn(cmd, options)
// 这里的 cmd代表命令 如 keytool
// options 代表的是 参数 如 -alias
// 回调
result.stdout.on("data", data => { });
//输出报错信息
result.stderr.on("data", err => {
console.log("输出错误信息:", err.toString())
});
//当程序执行完毕后的回调,那个code一般是0
result.on("exit", code => {})
这个具体的keytool命令,之前已经讲过了,本文也给了链接,可以去看一看!
证书文件处理
指定静态目录
使用koa-static(需安装)指定静态目录,我这里就以resources命名(根目录)
const Koa = require('koa')
const app = new Koa()
app.use(require('koa-static')(__dirname + '/resources'))
创建唯一目录
使用uuid作为唯一
const { v4: uuidv4 } = require('uuid');
const fsPromises = require('fs/promises');
// 唯一值
const _fileName = uuidv4()
// 目录全程
const fileName = "resources/android/" + _fileName + "/"
// 生成目录
// 前面文章有介绍此API
fsPromises.mkdir(fileName, { recursive: true })
移动文件(剪贴)
证书生成在根目录!
const fsPromises = require('fs/promises');
// 证书名称
const androidCretName = "android.keystore"
// fileName 是上文的唯一目录
fsPromises.rename(androidCretName, fileName + androidCretName)
响应请求
这里就是相当于把静态资源发送给前端
// 需下载
const send = require("koa-send")
// 响应类型
// path 就是路径
const contentType = 'application/octet-stream'
ctx.set('Content-Type', contentType)
ctx.attachment(path);
send(ctx, path)
删除资源
为了防止资源浪费,因为这里生成之后,证书就没用了,不会二次下载,所以把资源删了
const fsPromises = require('fs/promises');
// fileName 是上文的唯一目录
// 一分钟后自动清除 为了防止网速过慢,没下载完,资源没了
setTimeout(async () => {
await fsUtils.rm(fileName)
}, 60 * 1000)
建议可以写个定时任务,每天自动删除一遍,防止有异常出现,导致文件没删除干净!
前端处理
前端调用接口,传对应的参数之后就会拿到二进制流,然后进行下载,具体请查看下放文章
前端界面
「相关链接」
别人一键生成安卓证书网站:
https://www.applicationloader.net/keystore.html
我一键生成安卓证书网站:
https://www.lovingworld.top/utils/android-cert.html
关注公众号了解更多