我有一个带有Firebase数据库的移动应用程序。在应用程序中,客户通过手机App订购产品,我暂时没有添加需要注册的订单。商店在web面板中接收订单并回答客户。嗯,我创建了一些默认规则,但是Google已经告诉我,我的规则是不安全的,我必须更改它们。
// In this way the orders arrive from the mobile App to the database, but it is not secure
service cloud.firestore {
match / databases / {database} / documents {
match / {document = **} {
allow read, write: if true;
}
}
}
我已经改变了它们:
// In this way the orders made from the App do not reach the database
service cloud.firestore {
match / databases / {database} / documents {
match / {document = **} {
allow read: if true
allow write: if request.auth.uid == request.data.author_uid
}
}
}
我已经阅读了Firebase文档和这个网站上关于Firebase规则主题的答案,但是我不知道如何正确地编写我的规则。
使用第一种方式配置的规则,应用程序可以工作,但它们不安全。
当我将它们更改为第二个选项时,移动应用程序不会将订单发送到商店的web面板,因为它没有注册。
我应该如何配置我的规则,使他们是安全的,同时用户可以下订单?
我编辑问题重要的是:我的应用程序没有认证方法,在App中你不必注册就可以下订单
我必须说,应用程序没有身份验证,这是它的工作,但现在,任何人都可以下订单而不需要注册,因为应用程序目前没有这个功能
在数据库中,我只有两个集合:product(商店的产品)订单(app下的订单)
应用程序按照如下方式查询数据库:
订单进展:
const ProgresoPedido = () => {
const navigation = useNavigation()
const { idpedido, total } = useContext(PedidoContext)
const [tiempo, guardarTiempo] = useState(0)
const [completado, guardarCompletado] = useState(false)
const [totalBD, setTotal] = useState('')
useEffect(() => {
const obtenerProducto = () => {
firebase.db.collection('ordenes')
.doc(idpedido)
.onSnapshot(function (doc) {
guardarTiempo(doc.data().tiempoentrega)
guardarCompletado(doc.data().completado)
setTotal(doc.data().total)
})
}
obtenerProducto()
}, [])
这是产品查询:
const FirebaseState = props => {
// Crear state inicial
const initialState = {
menu: []
}
// useReducer with dispatch to execute functions
const [state, dispatch] = useReducer(FirebaseReducer, initialState)
// Function that is executed to bring the products
const obtenerProductos = () => {
// Consultar Firebase
firebase.db
.collection('productos')
.where('existencia', '==', true) // TRAE SOLO LAS EXISTENCIAS PLATOS QUE HAY
.onSnapshot(manejarSnapshot)
function manejarSnapshot(snapshot) {
let platos = snapshot.docs.map(doc => {
return {
id: doc.id,
...doc.data()
}
})
//Sort by category with lodash
platos = _.sortBy(platos, 'categoria')
//console.log(platos)
// We have the results from the database
dispatch({
type: OBTENER_PRODUCTOS_EXITO,
payload: platos
})
}
}
这些规则是不安全的,因为您允许任何经过身份验证的用户读取/写入数据库的任何部分。match /{document=**}
是一个递归通配符,它将规则应用于所有文档及其所有子文档。
假设您有一个用户集合和一个订单集合,如下所示:
users -> {userId}
(col) (doc)
orders -> {orderId}
(col) (doc)
你可以添加这些规则:
// In this way the orders made from the App do not reach the database
service cloud.firestore {
match /databases/{database}/documents {
match /users/{userId} {
allow read, write: if request.auth.uid === userId;
}
match /orders/{orderId} {
allow read, write: if request.auth.uid === resource.data.userId;
}
}
}
这些规则将允许创建该订单的用户只能读/写订单。您必须将userId存储在订单文档的字段中(在您的示例中为author_id
)。
当我将它们更改为第二个选项时,移动应用程序不会将订单发送到商店的web面板,因为它没有注册。
这是因为规则期望用户通过Firebase认证登录。
我没有添加需要注册的订单。
这就是Firebase匿名认证派上用场的地方。您可以创建一个新的匿名用户,它不需要用户的任何凭据,但将在Firebase Auth中创建一个具有UID的用户,该UID可以在Firebase文档中使用,并安全地存储用户的订单。
当用户即将完成订单时,可以将匿名帐户转换为永久帐户。这是强烈建议的,因为如果用户通过任何方式(包括显式退出或卸载应用程序)注销了他们的匿名帐户,那么相同的帐户(带有该UID)将永远无法恢复。
请注意,您还可以按照如下所示构建数据库:
user -> {userId} -> orders -> {orderId}
这样,您可能不需要将userId存储为每个订单文档中的字段。
建议在用户通过身份验证之前允许对其进行读/写访问。如果你公开允许你的用户,那么它会向你显示警告。
用给定的规则替换你的规则:
service cloud.firestore {
match /databases/{database}/documents {
match /{document=**} {
allow read, write: if request.auth != null;
}
}
}