让浏览器直传文件,密钥留在服务器
做后台时要上传图片,最直接的写法是浏览器把文件发给后端,后端再转存到对象存储。这样写能跑,但每张图都要占用服务器的带宽和内存,文件一大,接口就跟着变慢。
另一个想法是把存储的密钥发给前端,让它自己传,这更不能接受:前端的一切都在用户手里,密钥发出去就等于公开了。
更好的做法是预签名地址。服务器先校验文件类型和大小,再用密钥算出一个几分钟内有效的地址,浏览器拿到后直接上传。密钥没有离开服务器,流量也不经过服务器。
关键在于签名里写死了什么。把文件名、内容类型和长度都算进签名,这个地址就只能写这一个文件;有人想换成别的类型或者更大的文件,存储服务会直接拒绝。另外,SVG 里可以带脚本,图片白名单里不要放它。
备份没有恢复过,就不算备份
写一个定时导出数据库的脚本只要几分钟,但它能不能救命,要等到出事那天才知道。常见的坑有两个:导出中途失败,留下一个半截文件;或者文件一直在生成,却从来没人验证过它能不能恢复。
先落盘,再校验,最后上传。导出的数据如果直接通过管道传到云端,中途失败时半截文件也可能被当成“最新备份”。写到磁盘后用恢复工具读一遍目录,能读出来才上传。
定期真的恢复一次。每周把最新的备份恢复到一个临时库,检查表和数据行数,然后删掉。这件事交给定时任务,失败了发通知,比靠人记得去做可靠得多。
备份账号不给删除权限。过期文件交给存储桶的生命周期规则清理。这样即使服务器被入侵,攻击者也删不掉历史备份。
证书申请失败之后,服务可能不会马上重试
自动 HTTPS 很省心:配好域名,服务器就会自己申请和续期证书。但国内的服务器有个前提,域名要先完成备案,否则访问会被拦截,证书机构的验证请求也进不来。
我遇到的情况是,备案通过后,有的子域名已经有了证书,有的还在报 TLS 握手失败。配置都一样,看起来很奇怪。
看日志才明白:这几个域名的最后一次申请发生在备案通过之前,当时验证被拦截页挡住了。失败几次之后,服务会拉长重试间隔,避免频繁请求证书机构,所以备案通过后它们还在等下一次重试。
解决办法很简单,重启一次服务,它就会立刻重新申请。这件事给我的提醒是:遇到“配置一样、结果不同”的情况,先看每个对象各自的日志和时间线,别急着改配置。
判分这件事,只能放在服务端
做答题应用时,很容易想到把题目和答案一起发给前端,选完直接比较,体验又快又省接口。但前端的代码和数据都在用户手里,答案只要发下去,抓一次包就能看到。
所以规则很简单:考试类的功能,交卷前不返回任何答案。分数由服务端计算,客户端只负责展示。
交卷接口还要考虑两件事。一是幂等:网络不好时用户可能重复提交,同一份答卷只能算一次。二是用时:服务端自己记录开始时间,明显短得不合理的成绩不进排行榜,也不要相信客户端报上来的时长。
练习模式可以逐题提交、当场反馈,但判定同样在服务端完成。这样无论哪种模式,判分规则都只有一份,改起来也不会漏。