uni-app前端不可直接调用阿里云短信API,因阿里云强制服务端签名且AccessKeySecret严禁暴露于前端;正确做法是前端仅触发请求,由自有后端或uniCloud云函数完成鉴权、签名与调用,并通过环境变量管理密钥、按业务场景隔离缓存key、做好防刷与倒计时清理。

uni-app 前端不能直接调用阿里云短信 API
这是最常踩的坑:写个 uni.request 直连 dysmsapi.aliyuncs.com,开发工具里显示“发送成功”,真机却一条都不发,控制台也无报错。原因很硬——阿里云强制服务端签名,AccessKeySecret 绝对不可出现在前端代码里。uni-app 打包后 JS 可被反编译,密钥等于公开。
正确路径只有一条:uni-app 前端只负责触发和展示,所有鉴权、签名、调用必须落在服务端(自有后端或 uniCloud 云函数)。
- 前端调用的是你自己的接口,比如
/api/send-sms或uniCloud.callFunction({ name: 'sendSms' }) - 服务端用阿里云 SDK(如
@alicloud/dysmsapi20170525或aliyun-java-sdk-dysmsapi)完成真实请求 - 密钥必须存在服务端环境变量、配置文件或 uniCloud 云函数的「配置变量」中,绝不硬编码进前端
用 uniCloud 云函数是最简方案
如果你没自建后端,uniCloud 是最快落地的选择。它天然隔离密钥、免运维、支持按量计费(0.045 元/条),且 HBuilderX 内置调试友好。
实操要点:
- 在 uniCloud 云函数中安装依赖:
npm install @alicloud/dysmsapi20170525 @alicloud/openapi-client - 把
AccessKeyId、AccessKeySecret、SignName、TemplateCode全部设为云函数「环境变量」,代码里用process.env.ACCESS_KEY_ID读取 - 云函数入口接收
phone和可选scene(如'register'),先校验手机号格式/^1[3-9]\d{9}$/,再查 Redis 或云数据库做 60 秒防刷(key 建议设为sms:register:${phone}) - 生成 6 位随机码后,存入缓存(过期时间 5 分钟),再调阿里云 SDK 发送;成功才返回前端,失败要打日志并返回明确错误码
倒计时按钮必须绑定页面生命周期
常见现象:点击“获取验证码”后倒计时开始,切到微信再切回来,秒数卡死;或从登录页跳注册页,多个定时器叠加执行。根本原因是裸用 setInterval 没清理。
正确做法:
- 在
onLoad中启动倒计时,在onUnload或onHide中clearInterval - 用
ref或 data 字段存定时器 ID,避免闭包丢失引用 - 倒计时结束前禁止重复点击,按钮加
disabled+ loading 状态 - 若使用 Vue 3 + Composition API,推荐封装成
useSmsCountdownHook,自动响应页面卸载
后端验证时别漏掉缓存 key 的命名隔离
注册、登录、找回密码三个流程共用短信功能,但验证码不能混用。如果都存成 sms_codes[phone],用户注册时收到的码可能被误用于登录。
必须按业务场景隔离缓存 key:
- 注册:
sms:register:${phone} - 登录:
sms:login:${phone} - 找回密码:
sms:forget:${phone} - uniCloud 推荐用
uniCloud.database().collection('sms_cache')存,字段含phone、scene、code、expiresAt(Date 类型)
验证时先查对应 scene 的记录,再比对时间和码值。这一步漏掉,线上就可能出现“输错验证码反而登进去了”的安全问题。











