跳到主要内容

在 UniApp 中接入 CloudBase 用户认证

一句话定义:用 @cloudbase/adapter-uni-app@cloudbase/js-sdk 注册 UniApp 适配器,然后用 auth.signInWithSms / 微信一键登录拿身份,代码一份跑 H5 / 微信小程序 / 支付宝小程序 / 抖音小程序 / iOS / Android 六端,登录态共享。

预计耗时:50 分钟 | 难度:进阶

适用场景

  • 适用:团队是 UniApp(Vue3 + Composition API)跨端,想要一份代码同时出 H5、微信小程序、支付宝小程序、抖音小程序、iOS、Android
  • 适用:不想为每端重写一套认证,要一套 user 表 + 一套 uid
  • 适用:已经在用 add-auth-wechat-miniprogram 的纯小程序方案,现在要扩到多端
  • 不适用:纯微信小程序专属业务直接用 wx.cloud,不必上 UniApp 这一层
  • 不适用:Flutter / React Native / 鸿蒙原生场景,UniApp 适配器不覆盖,各自有专门 SDK
  • 不适用:UniApp x(纯原生编译模式),目前 @cloudbase/adapter-uni-app 只支持 UniApp 标准模式

环境要求

依赖版本
HBuilderX最新稳定版(3.99 及以上)
Node.js18
@cloudbase/js-sdk2.27.3
@cloudbase/adapter-uni-app1.5.0
Vue^3.4.x(Composition API)
编译器@vue/compiler-sfc3.4,UniApp vite 模板自带

另外需要:

  • 已开通的 CloudBase 环境 ID,地域选「上海」(短信验证码登录仅支持上海地域)
  • 控制台 → 身份认证 → 登录方式,把要用的几种方式开启:
    • 「短信验证码登录」(H5 / 支付宝小程序 / 抖音小程序 / App 共用)
    • 「微信小程序登录」(在微信小程序端做一键登录用)
    • App 端额外要在 环境配置 → 安全来源 → 移动应用安全来源 添加应用,拿 appSign + appAccessKey
短信验证码地域限制

短信登录仅支持上海地域。CloudBase init 时不传 region 默认就是上海;广州 / 北京环境用不了短信。

第一步:HBuilderX 创建 Vue3 项目,装 SDK

HBuilderX 顶部菜单 文件 → 新建 → 项目 → uni-app,模板选 Vue3 / Vite 版(默认勾选 Composition API)。

在项目根目录装 SDK 和适配器:

npm install @cloudbase/adapter-uni-app @cloudbase/js-sdk

UniApp Vue3 模板默认就有 package.json 和多端编译命令,不用额外配 vite。

第二步:初始化 cloudbase + 注册 adapter

关键:useAdapters 必须在 cloudbase.init 之前调用,顺序错了适配器不生效,SDK 会按浏览器环境跑,小程序端会全线报错。

src/utils/cloudbase.ts:

import cloudbase from '@cloudbase/js-sdk';
import adapter from '@cloudbase/adapter-uni-app';

// 1. 注册 UniApp 适配器,必须传 uni 对象(图形验证码弹窗要用)
const options = {
uni: uni,
};
cloudbase.useAdapters(adapter, options);

// 2. 初始化 SDK
export const app = cloudbase.init({
env: 'your-env-id',
// 仅 App 端(iOS / Android)需要这两项
// H5 / 各家小程序端可以不传或留空
appSign: 'your-app-sign',
appSecret: {
appAccessKeyId: 1,
appAccessKey: 'your-app-access-key',
},
});

export const auth = app.auth({
persistence: 'local', // 登录态本地长存,显式 signOut 才清
});

要点:

  • uni 对象在 UniApp 里是全局可用的,不用 import,直接传给 options.uni
  • App 端缺 appSign / appSecret 会在调云函数 / 数据库时报「app sign invalid」
  • persistence: 'local' 在每个端都映射到该端的持久化存储(H5 → localStorage、微信小程序 → wx.setStorage、支付宝 → my.setStorage、抖音 → tt.setStorage、App → uni.setStorage),业务不用关心底层

第三步:微信小程序端配合法域名 + 一键登录

3.1 微信公众平台配置合法域名

微信小程序后台 → 开发 → 开发管理 → 开发设置 → 服务器域名,把以下域名加入白名单(your-env-id 替换成你的环境 ID):

request 合法域名:

https://tcb-api.tencentcloudapi.com
https://your-env-id.service.tcloudbase.com

uploadFile 合法域名:

https://cos.ap-shanghai.myqcloud.com

downloadFile 合法域名:

https://your-env-id.tcb.qcloud.la
https://cos.ap-shanghai.myqcloud.com

域名按你 CloudBase 环境实际所在地域调整(广州环境是 ap-guangzhou,北京环境是 ap-beijing)。

3.2 微信小程序端用 uni.login 拿 code 走自定义登录

UniApp 跨端:微信小程序端用 uni.login({ provider: 'weixin' })code,前端把 code 传给云函数,云函数侧用 wx.openApi.auth.code2Sessionopenid,再用 CloudBase Auth Open API 给前端发自定义 ticket,前端 auth.signInWithCustomTicket(ticket) 完成登录。

src/pages/login/login.vue 一键登录入口:

import { auth } from '@/utils/cloudbase';

async function loginByWechatMP() {
// 1. 拿 code
const { code } = await uni.login({ provider: 'weixin' });

// 2. 调云函数换 ticket(云函数实现见下方)
const res = await uni.request({
url: 'https://your-env-id.service.tcloudbase.com/wxLogin',
method: 'POST',
data: { code },
});
const ticket = (res.data as any).ticket;

// 3. 用 ticket 登录
await auth.signInWithCustomTicket(ticket);
uni.reLaunch({ url: '/pages/index/index' });
}

云函数 wxLogin 的实现思路和 connect-openai-api-cloud-function 同一套(云函数侧持密钥),关键代码:

// 云函数:用 wxAppId + wxAppSecret 换 openid,再签自定义 ticket
const cloud = require('wx-server-sdk');
cloud.init();
exports.main = async (event) => {
const { code } = event;
const { openid } = await cloud.openapi({
appid: 'your-mp-appid',
}).auth.code2Session({ code });
const auth = cloud.auth();
const ticket = await auth.createTicket(openid, { refresh: 7200 * 1000 });
return { ticket };
};

微信小程序端不用走短信验证码,一键登录体验最好。

第四步:H5 / 支付宝 / 抖音端短信验证码登录

非微信小程序端走 v2 短信登录,两步:getVerification 拿 verificationInfo,signInWithSms 用验证码登录。

src/pages/login/login-sms.vue:

<template>
<view class="login">
<input
v-model="phone"
placeholder="+86 13800000000"
class="input"
/>
<button :disabled="countdown > 0" @click="sendCode">
{{ countdown > 0 ? `${countdown}s 后重发` : '获取验证码' }}
</button>
<input v-model="code" placeholder="6 位验证码" class="input" />
<button type="primary" @click="submit">登录</button>
<text v-if="err" class="err">{{ err }}</text>
</view>
</template>

<script setup lang="ts">
import { ref } from 'vue';
import { auth } from '@/utils/cloudbase';

const phone = ref('');
const code = ref('');
const err = ref('');
const countdown = ref(0);
let verificationInfo: any = null;

async function sendCode() {
err.value = '';
if (!/^\+86\s?\d{11}$/.test(phone.value)) {
err.value = '手机号格式应为 +86 13800000000';
return;
}
try {
verificationInfo = await auth.getVerification({
phone_number: phone.value,
});
countdown.value = 60;
const t = setInterval(() => {
if (countdown.value <= 1) {
clearInterval(t);
countdown.value = 0;
return;
}
countdown.value -= 1;
}, 1000);
} catch (e: any) {
err.value = e.message || '发送失败';
}
}

async function submit() {
err.value = '';
try {
await auth.signInWithSms({
verificationInfo: { verification_id: verificationInfo.verification_id },
verificationCode: code.value,
phoneNum: phone.value,
});
uni.reLaunch({ url: '/pages/index/index' });
} catch (e: any) {
err.value = e.message || '登录失败';
}
}
</script>

<style>
.input { border: 1rpx solid #ccc; padding: 16rpx; margin-bottom: 16rpx; }
.err { color: red; margin-top: 16rpx; display: block; }
</style>

要点:

  • 手机号必须带 +86 区号,SDK 接口校验严格
  • getVerification 返回的 verification_id 必须包在 verificationInfo 里传给 signInWithSms,不能直接传字符串
  • 同号 30 秒内只能发 1 条,日上限默认 30 条/天,在控制台 身份认证 → 登录方式 → 短信验证码
  • 控制台开启「短信登录」时如果勾选了「图形验证码」,前端要监听 uni.$on('CAPTCHA_DATA_CHANGE', ...) 把图形验证码图片渲染出来,用户输入后通过 uni.$emit('RESOLVE_CAPTCHA_DATA', { captcha_token, expires_in }) 回传,适配器才能继续走流程(适配器内部用事件总线,详见 UniApp adapter 文档)

第五步:App 端配 appSign + appSecret

App 端(iOS / Android)和小程序、H5 不一样,要在 CloudBase 控制台单独注册「应用安全来源」拿凭证。

控制台 → 环境配置 → 安全来源 → 移动应用安全来源 → 添加应用:

  • 应用名:随便起,比如 my-uniapp-ios
  • 应用包名(iOS 是 Bundle ID,Android 是 package name):和 manifest.jsonApp 模块配置 → AppID 对应的真机包名一致
  • 平台:iOS / Android 各加一条

提交后控制台会给:

  • appSign:对应 your-app-sign(应用标识)
  • appSecret.appAccessKey:对应 your-app-access-key(应用凭证)
  • appSecret.appAccessKeyId:版本号,默认 1

把这三个值填到 cloudbase.init 里:

cloudbase.init({
env: 'your-env-id',
appSign: 'my-uniapp-ios-sign',
appSecret: {
appAccessKeyId: 1,
appAccessKey: 'xxxxxx',
},
});

App 端短信登录用同一份代码,直接复用第四步的 login-sms.vue,不用改。

运行验证

不同端用不同命令编译,分别跑一遍:

# H5(浏览器)
npm run dev:h5

# 微信小程序(然后用微信开发者工具打开 dist/dev/mp-weixin)
npm run dev:mp-weixin

# 支付宝小程序(用支付宝小程序 IDE 打开 dist/dev/mp-alipay)
npm run dev:mp-alipay

# 抖音小程序(用抖音开发者工具打开 dist/dev/mp-toutiao)
npm run dev:mp-toutiao

App 端在 HBuilderX 顶部菜单 运行 → 运行到手机或模拟器,选真机或 iOS 模拟器。

每端验收 checklist:

  1. H5:用真实手机号走短信登录,Console 不应有错;成功后跳到首页,刷新页面登录态还在
  2. 微信小程序:点「微信一键登录」,授权后直接进首页,控制台 → 身份认证 → 用户管理 能看到 loginTypeWECHAT_OPEN_ACCESS_TOKEN(自定义登录)的用户
  3. 支付宝 / 抖音小程序:走短信登录,登录成功后能在用户管理里看到对应记录
  4. App:同手机号在 H5 端登录、再在 App 端登录,两端能拿到同一个 uid(说明 user 表共享)
  5. 退出登录:auth.signOut() 调一次,auth.hasLoginState() 返回 false,刷新页面也确实没登录态

常见错误

错误码 / 现象原因修复
全端 init 后所有调用报「unknown environment」/「sdk not init」cloudbase.useAdapters(adapter, options) 没在 cloudbase.init 之前调用严格保证 useAdapters 先于 init,且这俩调用不能拆到不同模块异步加载,否则不同端编译顺序不同会偶发挂掉
短信登录控制台开了图形验证码后,前端走到 getVerification 卡死,无响应adapter 的 options.uni 没传,适配器内部 uni.$emit('CAPTCHA_DATA_CHANGE', ...) 没法跑useAdapters(adapter, { uni: uni }) 必须显式传 uni 对象;前端页面要监听 CAPTCHA_DATA_CHANGE 事件、自己渲染图形验证码弹窗,用户输入后回传 RESOLVE_CAPTCHA_DATA
微信小程序端调云函数报「请求域名未配置」微信公众平台合法域名没加 tcb-api.tencentcloudapi.comyour-env-id.service.tcloudbase.com按第三步 3.1 把 4 类合法域名(request / uploadFile / downloadFile)全配齐
App 端 init 报 appSign invalid控制台「移动应用安全来源」添加的应用包名(Bundle ID / package name)和真机打包出来的不一致manifest.json 的 AppID + 平台配置里看真包名,严格一致(大小写敏感)
多端混用时同一手机号在 H5 登录、小程序端 auth.hasLoginState() 仍是 false登录态存在各端各自的存储里,跨端不会自动同步,跨端"共享 uid"指的是后端 user 表共享、不是前端登录态共享每端各自走一次登录流程;如果要做「一处登录全端可用」需要业务侧用同一手机号识别同一用户
短信发送报「该地域不支持短信」CloudBase 环境不在上海地域短信登录只在上海支持,在控制台新建上海环境 / 把项目迁过去,或者改用微信一键登录 + 自定义登录组合
抖音小程序端报「downloadFile 域名不在合法列表」抖音开发者后台没配 downloadFile 合法域名抖音开发者平台 → 开发管理 → 服务器域名https://your-env-id.tcb.qcloud.la 加上
Vue3 模板里 import adapter from '@cloudbase/adapter-uni-app' 报「Cannot find module」用了 Vue2 模板装的 SDK,或者 vite 别名没把 @cloudbase/* 排除 externals确认 HBuilderX 模板是 Vue3 / Vite 版,vite.config.ts 不要把 @cloudbase/* 写进 external

错误码定义参考 https://docs.cloudbase.net/error-code/

相关文档