Firebase实时数据库PERMISSION_DENIED权限拒绝问题求助
Firebase实时数据库PERMISSION_DENIED权限拒绝问题求助
我现在正在开发一个聊天应用,使用Firebase实时数据库,但一直遇到PERMISSION_DENIED: Permission denied的错误。我已经花了6小时尝试各种数据库规则,还是没能解决问题!
当前我的数据库规则配置如下:
{ "rules": { "chats": { "$chatId": { ".read": "auth != null", ".write": "auth != null" } } } }
以下是我的聊天组件代码(ChatScreen):
import { database, auth } from '../../../firebaseConfig'; import { ref, onValue, push } from 'firebase/database'; import { useLocalSearchParams, useRouter } from 'expo-router'; import { MaterialIcons } from '@expo/vector-icons'; import { useNetInfo } from '@react-native-community/netinfo'; import { useUser } from '@clerk/clerk-expo'; import { signInWithCustomToken } from 'firebase/auth'; const ChatScreen = () => { const { user } = useUser(); // 获取Clerk用户 const { buyerId, sellerId, shopData, sellerStatus } = useLocalSearchParams(); const [messages, setMessages] = useState([]); const [newMessage, setNewMessage] = useState(''); const router = useRouter(); const netInfo = useNetInfo(); const isConnected = netInfo?.isConnected; useEffect(() => { if (!user || !user.session) return; // 如果用户未认证则直接返回 // 获取Clerk会话并获取token const getClerkJwtToken = async () => { try { // 直接访问Clerk会话 const session = user.session; // 获取Clerk会话 const token = session?.access_token; // 从会话中获取token console.log('Clerk user:', user); const clerkToken = await user.getToken(); console.log('Clerk Token:', clerkToken); if (!token) { Alert.alert('Error', 'Failed to retrieve Clerk token'); return; } // 使用token登录Firebase认证 await signInWithCustomToken(auth, token); // 登录Firebase console.log("Firebase user authenticated with Clerk JWT"); } catch (error) { console.error("Error linking Clerk with Firebase", error.message); Alert.alert('Error', 'Failed to authenticate with Firebase'); } }; getClerkJwtToken(); // 调用函数完成Firebase认证 const chatId = `${buyerId}_${sellerId}`; const messagesRef = ref(database, `chats/${chatId}/messages`); const unsubscribe = onValue(messagesRef, (snapshot) => { const data = snapshot.val(); const messagesData = data ? Object.values(data) : []; setMessages(messagesData); }); return () => unsubscribe(); }, [buyerId, sellerId, user]); const sendMessage = async () => { if (newMessage.trim() === '') { Alert.alert('Error', 'Message cannot be empty.'); return; } if (!isConnected) { Alert.alert('Error', 'You are offline. Please check your connection.'); return; } const chatId = `${buyerId}_${sellerId}`; const messagesRef = ref(database, `chats/${chatId}/messages`); try { // 使用Clerk的user.id作为发送者ID await push(messagesRef, { senderId: user.id, // 使用Clerk用户ID作为发送者ID text: newMessage, timestamp: new Date().toISOString(), }); setNewMessage(''); } catch (e) { console.error('Error sending message:', e.message); Alert.alert('Error', e.message); } }; return ( <KeyboardAvoidingView style={styles.container} behavior={Platform.OS === 'ios' ? 'padding' : undefined} > {/* 头部 */} <View style={styles.header}> <TouchableOpacity onPress={() => router.back()} style={styles.backButton}> <MaterialIcons name="arrow-back" size={24} color="#333" /> </TouchableOpacity> <Image source={{ uri: shopData?.images?.profilePhoto }} style={styles.profilePic} /> <View style={styles.headerTextContainer}> <Text style={styles.sellerName}>{shopData?.shopName}</Text> <View style={styles.statusContainer}> <View style={[styles.statusIndicator, { backgroundColor: sellerStatus === 'online' ? 'green' : 'gray' }]} /> <Text style={styles.statusText}> {sellerStatus === 'online' ? 'Online' : 'Offline'} </Text> </View> </View> </View> {/* 消息列表 */} <FlatList data={messages} renderItem={({ item }) => ( <View style={item.senderId === user.id ? styles.buyerMessage : styles.sellerMessage}> <Text style={styles.messageText}>{item.text}</Text> </View> )} keyExtractor={(item, index) => `${item.timestamp}-${index}`} contentContainerStyle={styles.messagesContainer} /> {/* 输入框 */} <View style={styles.inputContainer}> <TextInput style={styles.input} value={newMessage} onChangeText={setNewMessage} placeholder="Type a message..." placeholderTextColor="#888" /> <TouchableOpacity style={styles.sendButton} onPress={sendMessage}> <MaterialIcons name="send" size={24} color="#fff" /> </TouchableOpacity> </View> </KeyboardAvoidingView> ); }; const styles = StyleSheet.create({ .. }); export default ChatScreen;
我用Clerk做用户认证系统,通过自定义token登录Firebase,日志里能看到Firebase user authenticated with Clerk JWT的输出,说明认证流程似乎是通的,但发送消息时还是触发权限拒绝错误。有没有大佬能帮我排查一下问题出在哪?
备注:内容来源于stack exchange,提问作者Mahmoud Hlal
相关产品推荐
相关产品推荐

