Firebase 和 Algolia 安全搜索没有搜索命中

Firebase and Algolia secured search no search hits

我在使用 Firebase 和 Algolia 实施安全搜索时遇到了一些问题。 我一直在遵循 https://firebase.google.com/docs/firestore/solutions/search -> 添加安全性

的指南

我的问题是似乎一切正常,但我没有收到任何搜索结果。

当用户搜索一个项目时,它会调用一个函数,该函数首先点击一个 firebase 函数来生成一个安全的 API 密钥,其中还包括用于查询的安全过滤器。

Firebase 函数:

app.use(getFirebaseUser);

app.get('/', (req, res) => {
  // @ts-ignore
  const uid = req.user.uid;

  // Create the params object as described in the Algolia documentation:
  // https://www.algolia.com/doc/guides/security/api-keys/#generating-api-keys
  const params = {
    // This filter ensures that only documents where author == uid will be readable
    filters: `ownerID:${uid}`,
    // We also proxy the uid as a unique token for this key.
    userToken: uid,
  };

  // Call the Algolia API to generate a unique key based on our search key
  const key = client.generateSecuredApiKey(ALGOLIA_SEARCH_KEY, params);

  // Then return this key as {key: '...key'}
  res.json({key});
});

这实际上是来自 firebase 示例的 copy/pasted,除了我将“作者”替换为“ownerID”,这是我想在我的索引中匹配的术语。

getFirebaseUser() 与官方 firebase 示例完全相同 copy/paste。

一旦客户端收到安全的 API 密钥,它就会通过查询传递给 algolia:

const getSearchResults = async (query: string) => {
  const index = client.initIndex('things');
  try {
    const userToken = await auth.currentUser?.getIdToken();
    const response = await fetch(GOOGLE_URL, {
      headers: { Authorization: `Bearer ${userToken}` },
    });
    const data = await response.json();
    const client = algoliasearch(ALGOLIA_APP_ID, data.key);
    const responses = await index.search(query);
    console.log(responses);
  } catch (err) {
    console.error(err.message);
  }
};

这也是和例子一样的功能,只不过写的是async/await。 (我确实尝试了一个精确的 copy/paste,结果是一样的)。 此外,该示例还显示了 index.search({query}),其中查询字符串作为对象传入。这也不起作用,Typescript 声明需要一个字符串。

如果我尝试将 initIndex 更改为不存在的索引,我会收到一条错误消息,指出它不存在。这告诉我我的应用程序和 algolia 之间的连接正在按预期工作。

返回的对象如下所示:

exhaustiveNbHits: true
hits: []
hitsPerPage: 20
nbHits: 0
nbPages: 0
page: 0
params: "query=test&filters=ownerID%3AKK3oXEkrIKb31BECDSJPMdgvTBz2&userToken=KK3oXEkrIKb31BECDSJPMdgvTBz2"
processingTimeMS: 1
query: "test"

如果我进行常规搜索:

const getSearchResults = async (query: string) => {
  const client = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_API_KEY);
  const index = client.initIndex('things');

  const responses = await index.search(query);
  console.log(responses);
};

我确实得到了点击:

exhaustiveNbHits: true
hits: Array(1)
0: {productName: "test ja", purchaseDate: "15.03.2021", purchasedFrom: "ok", ownerID: "KK3oXEkrIKb31BECDSJPMdgvTBz2", objectID: "25BadjQxUjRjkjH9ZnwW", …}
length: 1
__proto__: Array(0)
hitsPerPage: 20
nbHits: 1
nbPages: 1
page: 0
params: "query=test"
processingTimeMS: 1
query: "test"

这实际上是在绕过整个云功能,这意味着问题一定出在生成安全 API 密钥、参数或其他东西上。

Algolia 中存储的索引数据如下所示:

objectID "25BadjQxUjRjkjH9ZnwW"

productName "test ja"

purchaseDate "15.03.2021"

purchasedFrom "ok"

ownerID "KK3oXEkrIKb31BECDSJPMdgvTBz2"

这意味着我应该在 ownerID 上点击,我在云函数中有它。


编辑: 将参数对象的过滤器设置为空字符串时,我收到了搜索结果。过滤器的实现方式可能有问题。


感谢您对此进行调查。如果能得到所有帮助,我将不胜感激!

斯蒂芬·瓦卢瓦

我正在接触 algolia,并找出问题所在。

代码或搜索的设置方式没有任何问题。 文档中没有提到的一件事是我匹配的属性 (ownerID) 没有声明为分面属性。

通过转到 Algolia 应用程序中的配置 -> Facets,并在那里添加对象键,一切都按预期进行。 (将其设置为 'not searchable')。此属性不应该是可搜索的。它应该只用于将索引与正确的用户匹配。

如果有人使用 Algolia 进行安全搜索,无论您是否使用 Firebase 函数或其他后端,都必须在 Facets 中设置过滤器中的属性。