Firebase Realtime Database规则中OR运算符顺序不同执行结果异常
问题原因分析
这个问题的核心是Firebase Realtime Database安全规则的短路求值特性和异常直接判定为拒绝的机制导致的,和||逻辑本身的语义无关:
- 你提供的数据库结构中,
$gameID节点下直接存储的是下标为0、1的玩家数组,不存在players子节点。第一个规则先执行newData.child('players').child('0').child('userID').val().contains(auth.uid)时,路径不存在导致val()返回null,对null调用contains()方法会直接抛出类型异常。安全规则只要求值过程中抛出异常,会直接判定整个.write规则为false,不会继续执行||后面的分支,所以规则直接失效。 - 调换顺序后,规则先执行
newData.child('0').child('name').val().contains(auth.uid),这个路径和你的数据库结构匹配,val()返回字符串,调用contains()不会抛出异常,只要该条件满足,||后面的players相关分支会被短路不执行,自然不会触发异常,所以规则可以正常生效。
规则优化建议
- 先判断路径存在再调用方法,避免空值异常:可以在访问
players下的字段前先加newData.hasChild('players')判断,避免路径不存在时的空值报错。 - 把公共判断条件提前:你的两个分支都包含
!data.exists(),可以提取到外层减少重复求值:
".write": "auth != null && !data.exists() && ( (newData.child('0').child('name').val().contains(auth.uid) || newData.child('1').child('name').val().contains(auth.uid) || newData.child('2').child('name').val().contains(auth.uid) || newData.child('3').child('name').val().contains(auth.uid)) || (newData.hasChild('players') && (newData.child('players').child('0').child('userID').val().contains(auth.uid) || newData.child('players').child('1').child('userID').val().contains(auth.uid) || newData.child('players').child('2').child('userID').val().contains(auth.uid) || newData.child('players').child('3').child('userID').val().contains(auth.uid)) ))"
内容的提问来源于stack exchange,提问作者ursan526
相关产品推荐
相关产品推荐

