2019-11-03 更新:添加了错误的实时最小再现 https://shardautherror.firebaseapp.com。在 Chrome 中加载链接后,按 ctrl+shift+i 并选择控制台以查看输出。我已尽力确保这完全符合我原始项目代码的功能;我们会看看情况是否如此,是吗?分片的规则文件与下面的原始帖子相同。这源代码可以在 GitHub 上找到 https://github.com/ChrisChiasson/shardAuthError.
<!DOCTYPE html>
<html>
<body>
<script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-auth.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.2.3/firebase-database.js"></script>
<script>
const config={
apiKey: "AIzaSyDLMc0GUf5n2nQa3aqpELQu7lziprQOGs8",
authDomain: "shardautherror.firebaseapp.com",
databaseURL: "https://shardautherror.firebaseio.com",
projectId: "shardautherror",
storageBucket: "shardautherror.appspot.com",
messagingSenderId: "841096336504",
appId: "1:841096336504:web:9899961c8250caa552498d"
};
const shard="https://shardautherror-1e9ed.firebaseio.com/";
async function init(){
try{
firebase.database.enableLogging(true);
const defaultApp=firebase.initializeApp(config);
const auth=defaultApp.auth();
const s="[email protected] /cdn-cgi/l/email-protection";
await auth.signInWithEmailAndPassword(s,s);
const uid= auth.currentUser.uid;
const shardApp=firebase.initializeApp({databaseURL:shard},'dbAppShard');
const db=firebase.database(shardApp);
const ref= db.ref("/chat/"+uid+"/fail/"+uid);
const time= firebase.database.ServerValue.TIMESTAMP;
ref.set({time});
} catch(e) {
console.error("init failed",e);
}
}
init();
</script>
</body>
</html>
原帖:
这些规则在模拟器中有效,但在我真正的网络应用程序中无效。模拟器路径和负载与下面的数据库日志输出中所示的相同。
database.rules.json
(main
目标两个分片都使用此规则文件;我在部署时验证)
{
"rules":{
"chat":{
"$ownerId":{
"fail":{
"$pId":{
".write": "$pId== auth.uid&& $ownerId== auth.uid",
"time":{".validate": "newData.val()== now"},
"$other":{".validate": "newData.isString()&& newData.val().length>= 28"}
}
}
}
}
}
}
Firebase 记录失败的 set 命令的输出。它只写入一个称为时间的值。这是我第一次尝试使用rtdb。我已经将其设置为分片。它在尝试访问实时数据库之前从 firestore 获取分片名称,但它看起来不像竞争条件(尽管有日志输出),原因我将在下面概述。
index.esm.js:81 [2019-10-19T03:02:53.281Z] @firebase/database: 0: set
{"path":"/chat/rpNIK41hNpWkYY2KqndkwCzPJuF3/fail/rpNIK41hNpWkYY2KqndkwCzPJuF3",
"value":{"time":{".sv":"timestamp"}},"priority":null}
22:02:53.285 index.esm.js:81 [2019-10-19T03:02:53.285Z] @firebase/database:
p:0: Buffering put: /chat/rpNIK41hNpWkYY2KqndkwCzPJuF3/fail/rpNIK41hNpWkYY2KqndkwCzPJuF3
22:02:53.293 index.esm.js:81 [2019-10-19T03:02:53.293Z] @firebase/database:
p:0: Making a connection attempt
22:02:53.294 index.esm.js:81 [2019-10-19T03:02:53.294Z] @firebase/database:
getToken() completed. Creating connection.
22:02:53.295 index.esm.js:81 [2019-10-19T03:02:53.295Z] @firebase/database:
c:0:0: Connection created
22:02:53.296 index.esm.js:81 [2019-10-19T03:02:53.296Z] @firebase/database:
p:0: Auth token refreshed
22:02:53.298 index.esm.js:81 [2019-10-19T03:02:53.298Z] @firebase/database:
c:0:0:0 Websocket connecting to wss://quickstart-1551998385825-7f7a6.firebaseio.com/.ws?v=5
22:02:53.534 index.esm.js:81 [2019-10-19T03:02:53.534Z] @firebase/database:
c:0:0:0 Websocket connected.
22:02:53.539 index.esm.js:81 [2019-10-19T03:02:53.539Z] @firebase/database:
c:0:0: Realtime connection established.
22:02:53.539 index.esm.js:81 [2019-10-19T03:02:53.539Z] @firebase/database:
p:0: connection ready
22:02:53.542 index.esm.js:81 [2019-10-19T03:02:53.541Z] @firebase/database:
p:0: reportStats {"c":{"sdk.js.7-0-0":1}}
22:02:53.542 index.esm.js:81 [2019-10-19T03:02:53.542Z] @firebase/database:
p:0: {"r":1,"a":"s","b":{"c":{"sdk.js.7-0-0":1}}}
22:02:53.546 index.esm.js:81 [2019-10-19T03:02:53.546Z] @firebase/database:
p:0: {"r":2,"a":"p","b":{"p":"/chat/rpNIK41hNpWkYY2KqndkwCzPJuF3/fail/rpNIK41hNpWkYY2KqndkwCzPJuF3",
"d":{"time":{".sv":"timestamp"}}}}
22:02:53.591 index.esm.js:81 [2019-10-19T03:02:53.591Z] @firebase/database:
p:0: from server: {"r":1,"b":{"s":"ok","d":""}}
22:02:53.595 index.esm.js:81 [2019-10-19T03:02:53.595Z] @firebase/database:
c:0:0: Primary connection is healthy.
22:02:53.596 index.esm.js:81 [2019-10-19T03:02:53.596Z] @firebase/database:
p:0: from server: {"r":2,"b":{"s":"permission_denied","d":"Permission denied"}}
22:02:53.597 index.esm.js:81 [2019-10-19T03:02:53.597Z] @firebase/database:
p:0: p response {"s":"permission_denied","d":"Permission denied"}
所以,在此之后,如果我将规则更新为".write": true,
时间戳写入成功。在日志中它显示"r":3 ...
,所以我知道它没有丢弃连接并重新启动。如果我然后将其更改为".write": "auth.uid != null",
or ".write": "auth != null",
(因此,不检查所有权,只检查客户端是否登录,与上面不同)它再次拒绝权限"r":4 ..."
表示第四个请求。所以,看来我的客户端完全无法对分片进行身份验证。
Simulator output:
建议?我确信我做错了什么。
顺便说一句,用户文档到处都是......所有这些实际上都有效吗?
"baskets": {
".read": "auth.uid != null &&// auth.uid!= null from https://firebase.google.com/docs/database/security/securing-data
".read": "auth != null && auth.uid == $uid" // auth != null from https://firebase.google.com/docs/database/security/user-security
".write": "$user_id === auth.uid" // triple equal from https://firebase.google.com/docs/database/security/user-security
".write": "request.auth.uid == uid" // request.auth from realtime database tab of content owner access from https://firebase.google.com/docs/rules/basics