白银狮子头
白银狮子头
  • 发布:2022-01-21 00:16
  • 更新:2022-01-26 15:46
  • 阅读:966

clientDB schema read 权限问题 {"code":"PERMISSION_ERROR"}

分类:uniCloud

自定义的collection,指定permission为:

	"permission": {  
		"read": "(doc.createdBy == auth.uid)",  
		"create": false,  
		"update":false,  
		"delete": false  
	},  
  
		"createdBy": {  
			"title": "录入者用户ID",  
			"bsontype": "string",  
			"forceDefaultValue": {  
				"$env": "uid"  
			},  
			"foreignKey": "uni-id-users._id"  
  
		},

希望仅为创建者的用户可以看到自己创建的记录。
但是从模板<unicloud-db></unicloud-db>访问时候,获得错误

**
00:07:05.856 onDataError(): error = {"code":"PERMISSION_ERROR"}
00:07:05.861 a: 权限校验未通过
**

如果权限改为

"permission": {  
		"read": "(xxxx == auth.uid)",  
		......  
}

xxxx为具体的uid

或者

"permission": {  
		"read": "'XYZ_USER' in auth.role",  
		......  
}

都可以正常读取。
请问这是为什么呢?

我希望最终实现类似这样的效果:

"permission": {  
		"read": "(('XYZ_USER' in auth.role) && (doc.createdBy == auth.uid))) || (‘XYZ_ADMIN’ in auth.role)",  
		......  
}

就是要求要么有某业务管理员角色就都能看到,要么有该业务的用户角色、且只能访问自己创建的记录。
请问应该怎么写?

2022-01-21 00:16 负责人:无 分享
已邀请:
DCloud_uniCloud_WYQ

DCloud_uniCloud_WYQ

"permission": {    
        "read": "(('XYZ_USER' in auth.role) && (doc.createdBy == auth.uid))) || ('XYZ_ADMIN' in auth.role)",    
        ......    
}

就是这么写的,但是你这段代码引号写错了

  • 白银狮子头 (作者)

    谢谢答复!不过——


    没有解释我前面的简单写法为什么不行  

    "permission": {  

    "read": "(doc.createdBy == auth.uid)",

    "create": false,

    "update":false,

    "delete": false

    },

    其实最后我写的那段是手敲的,所以有引号的错误。实际在schema文件里,没有这个错误。  

    我的schema是对的。

    如果我的Schema是错的,会有另外的错误,不是“PERMISSION_ERROR”,而是“SYSTEM_ERROR”或者别的类似的。这个我试过。

    还是要问清楚这两个问题,请指教


    2022-01-21 12:58

  • DCloud_uniCloud_WYQ

    回复 白银狮子头: 你如果用了doc,那么权限校验就跟你传了什么样的where有关,贴出来看一下,另外可以在HBuilderX的JQL管理器里面执行一下你的查询看看,是不是能查到你配置的权限之外的数据


    2022-01-21 14:44

  • 白银狮子头 (作者)

    回复 DCloud_uniCloud_WYQ: 我特意没有写任何的Where


    <unicloud-db ref="udb" v-slot:default="{data, pagination, loading, hasMore, error}"  
    collection="invoices"
    field="code,number,amount,issuedDate,rawQRCode,deleted,claimantName,memo,createdByUsername"

    loadtime="manual"
    @load="onDataLoad"
    @error="onDataError">
    <scroll-view :scroll-y="true" v-if="hasLogin">
    <uni-list scrollY="true" v-for="(item, index) in data" :key="item._id" :id="item._id">
    <uni-list-item class="ul"
    showArrow :clickable="true" @click="onInvoiceClicked(item,index)"
    thumb="/static/img/fapiao-hei.png" thumbSize="lg"
    :title="new Date(item.issuedDate).toLocaleDateString()"
    :claimantName = "'申请人: ' + item.claimantName"
    :note="'备注:' + item.memo"
    :ellipsis="2"
    :rightText="'开票金额: '+String(item.amount)"
    >
    <template v-slot:body>
    <view class="uni-list-item__content uni-list-item__content--center">
    <view class="uni-list-item__content-issueddate">开票日期:<uni-dateformat :date="item.issuedDate" format="yyyy-MM-dd" /></view>
    <!-- <text class="uni-list-item__content-issueddate">开票日期:<uni-dateformat :date="item.issuedDate" format="yyyy-MM-dd" class="uni-list-item__content-issueddate" /></text> -->
    <text class="uni-list-item__content-title">申请人:{{item.claimantName}}</text>
    <text class="uni-list-item__content-title">填写人:{{item.createdByUsername}}</text>
    <text class="uni-list-item__content-note uni-ellipsis-2">备注: {{ item.memo}}</text>
    </view>
    </template>
    </uni-list-item>
    </uni-list>
    </scroll-view>
    <uni-load-more :status="loading?'loading':(hasMore ? 'more' : 'noMore')"></uni-load-more>
    </unicloud-db>

    中间空了 一行,是我把:where给删除了


    :where="queryWhere"

    以前的queryWhere是我在computed 里面定义的:


      
    computed: {
    ...mapState(['forcedLogin', 'hasLogin', 'userName', 'userId']),
    queryWhere() {
    console.log('computed queryWhere(): userId '+ this.userId);
    let query = this.claimedOrCreated ? `claimantId=="${this.userId}"` : `createdBy=="${this.userId}"`
    if (this.search_keyword){
    // string和RegExp类型不同,没法相加
    // query += `${new RegExp(this.search_keyword, 'i')}.test(memo)`

    // 拼凑后半部分query,要求memo包含search_keyword
    query += '&& \/'+this.search_keyword+'\/.test(memo)'
    }
    console.log('computed queryWhere(): query = '+ query)
    return query
    },
    switchBtnText(){
    return this.claimedOrCreated ? '按申请人' : '按录入人'
    }
    },

    这段queryWhere()是要被替换掉的,目前在<unicloud-db></unicloud-db>中被删掉了


    2022-01-21 15:26

  • 白银狮子头 (作者)

    而且我特意使用了导入的uni-id-users这个collection做了实验。这个collection来自UniID,我以前没改过。

    我修改了其中的permission中的read,类似


    	"permission": {  
    "read":"(doc._id == auth.uid)"
    },

    这样的,也是不行的


    2022-01-21 15:31

  • 白银狮子头 (作者)

    回复 DCloud_uniCloud_WYQ:

    JQL查询可以查出所有的数据

    比如

    uni-id-users 的permission是:


    	"permission": {  
    "read":"(doc._id == auth.uid)"
    },

    JQL查询是


    db.collection('uni-id-users').get();

    结果能获得所有的数据,完全没有限制。


    2022-01-21 16:45

白银狮子头

白银狮子头 (作者) - 不是我不明白,这技术变化快!

还有没进一步的解答?

  • DCloud_uniCloud_WYQ

    正面的回答一下我这个问题 你如果用了doc,那么权限校验就跟你传了什么样的where有关,贴出来看一下,另外可以在HBuilderX的JQL管理器里面执行一下你的查询看看,是不是能查到你配置的权限之外的数据


    2022-01-22 14:24

  • DCloud_uniCloud_WYQ

    也就是说where应该是权限的子集


    2022-01-22 14:24

  • 白银狮子头 (作者)

    回复 DCloud_uniCloud_WYQ:



    1. 我没有使用where,就是查询全部数据,上面的


    <unicloud-db ref="udb" v-slot:default="{data, pagination, loading, hasMore, error}"    
    collection="invoices" field="code,number,amount,issuedDate,rawQRCode,deleted,claimantName,memo,createdByUsername"
    loadtime="manual"
    @load="onDataLoad"
    @error="onDataError">
    </unicloud-db>


    1. HBuilderX中执行JQL:


    db.collection('invoices').get();

    返回了全部invoices的数据,无论我如何设定permission,都返回全部数据


    2022-01-22 15:23

白银狮子头

白银狮子头 (作者) - 不是我不明白,这技术变化快!

  1. 是不是在schema中,collection级的“schema”不能用于筛选匹配的记录?
    比如我用“read”:"doc.createdBy == auth.uid",间接实现了访问用户只能访问自己创建的记录的效果。
    这样是不支持的,对不对?

  2. 是不是collection的permission,不允许比较“==”两边都是变量的情况,而是至少要有一边是常量?
    比如
    "doc.createdBy == auth.uid"是不能通过的,永远返回“PERMISSION_ERROR”
    但是
    “'12345678' == auth.uid”是有可能通过的

  3. 是不是collection的permission,一旦使用“doc.xxx==‘12345678’”,就必须要求全集合的每一条都满足‘12345678’才能返回true并允许访问整个collection;一旦有一条记录不满足条件,就不能访问?
    Schema权限文档里描述了“表级权限”、“字段权限”,这个我理解。但是指定数据集权限控制 里面提到的可以根据doc的某个字段决定可以访问那些数据,这个效果尝试不出来啊。

  • DCloud_uniCloud_WYQ

    where应该是权限的子集 不传where的情况下就表示你要访问全集,那是没法通过你配置的doc._id == auth.uid权限的,permission不是用来筛选数据的,只是用来校验权限


    2022-01-24 11:37

  • 白银狮子头 (作者)

    回复 DCloud_uniCloud_WYQ:

    但是我想隔离各个普通用户,防止他们互相浏览数据,这个怎么办?

    仅仅从Where着手的话,无法防止客户端篡改页面或者storage里的where表达式。


    而且我试了试uni-id-users表中保留


    "permission":{  
    "read": "doc._id == auth.uid"
    },

    并在<unicloud-db>中增加了where="'status'==0",但是用户登录后仍然是返回“a: 权限校验未通过”的错误


    2022-01-24 16:54

  • DCloud_uniCloud_WYQ

    回复 白银狮子头: where('_id==$cloudEnv_uid')


    2022-01-24 17:28

  • 白银狮子头 (作者)

    这样把where的表达式放在web端来生成,并发回server,不会被注入、或者被打开调试窗口替换吗?


    2022-01-24 22:38

  • DCloud_uniCloud_WYQ

    回复 白银狮子头: 替换也没问题,校验权限是在云端进行的


    2022-01-25 11:10

  • 白银狮子头 (作者)

    回复 DCloud_uniCloud_WYQ:

    可是uniCloud说,可以不用云函数,只用<unicloud-db>标签就可以安全访问的。

    我只在where里传递id,如果被人用调试界面替换成其他人的id,就可以直接访问其他人录入的信息了啊


    2022-01-25 16:56

  • DCloud_uniCloud_WYQ

    回复 白银狮子头: 你的permission是配置在schema里面的,schema来校验权限,前端传错了自然没法通过


    2022-01-26 14:39

  • DCloud_uniCloud_WYQ

    回复 白银狮子头: 例如你permission规定doc.user_id == auth.uid,那这个用户就只能访问这个表里面user_id等于他的id的记录。除非他能把别人的token也偷来,不然不可能越过权限校验


    2022-01-26 14:40

  • 白银狮子头 (作者)

    回复 DCloud_uniCloud_WYQ:

    但是事实上,我这么设定就直接报错,PERMISSION_ERROR,根本不能访问,而不是只能访问自己的。


    2022-01-26 15:45

  • DCloud_uniCloud_WYQ

    回复 白银狮子头: 你再好好理解理解我上面说的吧,现在表现是对的


    2022-01-26 17:10

白银狮子头

白银狮子头 (作者) - 不是我不明白,这技术变化快!

我说的不是传错了,而是在前端进行替换,故意传入别人的ID,以偷窥别人数据,怎么防?

  • 3***@qq.com

    你的ID在你的token中,对方要替换你的Token,

    需要知道你的加密算法才能修改ID并算出来能通过云端校验的token,

    具体来说,就是uni-id下的config.json中的配置内容,这个对方没办法拿到吧,你会主动告诉人家?


    2023-02-26 10:48

该问题目前已经被锁定, 无法添加新回复