Firebase实时数据库自定义JWT认证后如何配置房间级安全规则
实时数据库安全规则配置方案(自定义Auth聊天应用)
问题背景
基于Firebase实时数据库开发聊天应用,用户验证通过自有服务器完成,未使用Firebase Auth原生服务。已按照Frank van Puffelen的建议生成JWT并通过自定义Token完成Firebase Auth登录,现需配置数据库规则,确保用户仅能读写自己参与的聊天房间(房间ID格式如9810012345-9810012346,为两个用户ID拼接而成),禁止访问不属于自己的房间。
当前完整流程
- 用户通过自有凭证登录,服务器使用PHP Firebase JWT生成JWT:
$Token = JWT::encode($request_data,$secret_Key,'HS512');
登录成功后将Token返回给应用。
- 应用调用Firebase Auth接口完成登录:
firebaseAuth = FirebaseAuth.getInstance(); firebaseAuth.signInWithCustomToken(Session.getJWT()) .addOnCompleteListener(new OnCompleteListener<AuthResult>() { @Override public void onComplete(@NonNull Task<AuthResult> task) { if (task.isComplete()){ Intent intent=new Intent(getActivity(),MainActivity.class); getActivity().startActivity(intent); } } });
- 用户点击聊天按钮时,检查房间是否存在,不存在则创建:
DatabaseReference db = FirebaseDatabase.getInstance().getReference(); db.addListenerForSingleValueEvent(new ValueEventListener() { @Override public void onDataChange(DataSnapshot dataSnapshot) { if (dataSnapshot.hasChild(RoomTitle)) { RoomName(RoomTitle, true); }else { RoomName(RoomTitle, false); } } @Override public void onCancelled(DatabaseError databaseError) { } }); public void RoomName(String Name, boolean RoomExist) { button_SendMessage.setEnabled(true); if (!RoomExist) { Log.d(TAG, "Room Not Exist Creating One"); Map<String, Object> RoomNameMap = new HashMap<>(); RoomNameMap.put(Name, ""); FirebaseDatabase.getInstance().getReference().updateChildren(RoomNameMap); } // Launch Chat Screen }
- 进入聊天界面后关联对应房间的数据库节点:
databaseReference = FirebaseDatabase.getInstance().getReference().child(Room_Name);
数据库规则配置
核心思路
利用房间ID的格式特征(两个用户ID用-拼接),在规则中验证当前登录用户的UID是否为房间ID中的其中一个用户ID,以此限制读写权限。
规则代码
{ "rules": { "$roomId": { ".read": "auth != null && ($roomId.split('-')[0] == auth.uid || $roomId.split('-')[1] == auth.uid)", ".write": "auth != null && ($roomId.split('-')[0] == auth.uid || $roomId.split('-')[1] == auth.uid)" } } }
关键说明
- JWT字段要求:生成JWT时,必须将用户的自有唯一标识(如示例中的
9810012345)设置为JWT的uid字段,确保Firebase Auth登录后auth.uid能正确映射到用户的自有ID。例如PHP中$request_data需包含:
$request_data = [ "uid" => "用户自有唯一ID", // 其他必要声明 ];
- 权限验证逻辑:规则先检查用户已登录(
auth != null),再通过split('-')分割房间ID,判断当前用户UID是否为房间的两个参与者之一,符合条件则允许读写。 - 房间创建权限:当前流程中直接在根节点创建房间,上述规则已覆盖创建场景——用户创建房间时,
$roomId为目标房间名,规则会验证用户是否为房间参与者,符合条件则允许创建。
内容的提问来源于stack exchange,提问作者androidXP
相关产品推荐
相关产品推荐

