unicloud数据库操作必须封装在云函数中,前端直连unicloud.database()必然失败;权限需在控制台schema中手动配置并上传,且字段名须用下划线命名(如user_name),jql支持动态权限校验。

uniCloud 数据权限必须在云函数里控制,前端直连数据库永远失败
uni-app 前端调用 uniCloud.database() 查不到数据或返回 permission denied,不是代码写错了,而是架构违规。uniCloud 的数据库权限不靠前端代码开关,而靠「云函数封装 + 控制台 Schema 配置」双生效。所有 DB 操作必须进云函数,哪怕只是 get() 一条记录。
常见错误现象:{{data?.id}} 渲染为空、loading 一直为 true、控制台报 TOKEN_INVALID_ANONYMOUS_USER。这些都不是前端没等数据,而是请求根本没过权限校验层。
- 前端禁止出现
uniCloud.database().collection('users').get()这类直连语句 - 数据库字段名避免驼峰(如
userName→ 改成user_name),否则 Schema 权限配置会失效 - Schema 中的
read和write权限必须手动开启,且支持 JQL 表达式(如"auth == $cloudEnv_uid || role == 'admin'") - 若用到
$cloudEnv_uid,需确认已启用uni-id,否则该变量为空
动态分配权限的核心是 JQL + 云函数参数 + 用户角色实时计算
权限不能硬编码在 Schema 里,得靠云函数接收运行时参数(比如当前操作目标 ID、用户角色上下文),再拼出带条件的 JQL 查询。比如一个审批列表,普通员工只能看自己提交的,管理员能看全部:
// cloudfunctions/list-approvals/index.js
exports.main = async (event, context) => {
const { role, target_id } = event // 前端传入的动态参数
let jql = 'status == "pending"'
if (role === 'admin') {
jql += ''
} else {
jql += ` && user_id == $cloudEnv_uid`
}
return await db.collection('approvals').where(jql).get()
}
关键点:JQL 中的 $cloudEnv_uid 是服务端自动注入的当前用户 ID,不可伪造;role 必须由前端从 uniCloud.getCurrentUserInfo() 获取并传入,不能只靠前端判断——因为角色可能刚被后台修改,缓存未刷新。
- 不要在前端用
v-if="role === 'admin'"控制按钮显示,这属于“伪权限”,后端仍要校验 - 云函数内可通过
context.user或uniCloud.getProvider().getCurrentUserInfo()获取完整用户信息,比前端传的更可信 - JQL 不支持复杂逻辑(如嵌套三元),需要多条件时建议拆成多个云函数,或用
db.collection().aggregate()
前端调用时 name 必须与云函数文件夹名完全一致,大小写敏感
uniCloud.callFunction 报 undefined 或 “function not found”,90% 是部署和调用不匹配。这不是网络问题,而是路径映射失败。
部署动作必须右键整个云函数文件夹(如 uniCloud/cloudfunctions/list-approvals)→「上传部署」,只保存 index.js 不生效。前端调用时的 name 参数必须和这个文件夹名**逐字符一致**:
- ✅ 正确:
name: 'list-approvals' - ❌ 错误:
name: 'List-Approvals'、name: 'list_approvals'、name: 'list-approvals/index' - H5 端调试必须勾选 manifest.json → H5 配置 →「使用本地云函数」,否则走 CORS 被拦截
- 小程序真机调试前,HBuilderX 右键
uniCloud目录 →「切换服务空间」,确保和云函数部署空间一致
权限变更后前端如何实时感知?别依赖 localStorage 缓存
用户在后台被升为管理员,但前端页面仍显示“无权限”,是因为角色信息缓存在 uni.getStorageSync('role') 里没更新。uniCloud 本身不提供“权限推送”机制,必须主动拉取。
最稳妥的做法是:每次进入敏感页面前,先调一次轻量级云函数查当前角色,再决定渲染逻辑。例如:
// 页面 onShow 中
const res = await uniCloud.callFunction({ name: 'get-user-role' })
if (res.result.role !== 'admin') {
uni.showToast({ title: '权限不足', icon: 'none' })
return
}
这个云函数只需返回 { role: 'admin' },不查数据库,性能开销极小。比起全局监听或定时轮询,它更精准、可控。
容易被忽略的是:uniCloud.getCurrentUserInfo() 返回的数据可能滞后,因为它读的是 token payload 缓存;真正权威的角色来源,是云函数里查 uni-id-users 表或你自定义的角色表。











