首页 > 解决方案 > 清理 ElasticSearch 参数?

问题描述

我有一个 api,它是弹性搜索集群的入口点。api对于我翻译成 ES POST 查询的许多xxx.contains=,yyy.in=和输入参数来说并不是微不足道的。zzz.equals=然后我使用 axios 直接查询 ES 集群。它工作正常。

const buildElasticSearchRequestBody = (page, size, params) => {
  //highlighting options https://www.elastic.co/guide/en/elasticsearch/reference/6.8/search-request-highlighting.html
  let requestBody = {
    from: page * size,
    size: size,
    highlight:
      params.highlight === "true" || params.highlight == true
        ? highlightOptions
        : {},
  };

  let must = [];

  //For now we are doing an AND across supplied field predicates- AND in ES is 'must'
  let queryObj = {
    bool: {
      must: must,
    },
  };

  for (const [key, value] of Object.entries(params).filter((pair) =>
    searchTypes.some((searchType) => pair[0].includes(searchType))
  )) {
    if (!allowedSearches.includes(key)) {
      throw new Error(`Search key ${key} is not permitted currently`);
    }

    //we need to exclude empty or undefined params but allow true/false
    if (value === "" || value == undefined) {
      continue;
    }

    const field = key.split(".")[0];

    //.contains queries are ES 'match's
    //https://www.elastic.co/guide/en/elasticsearch/reference/master/query-dsl-match-query.html
    if (key.includes(".contains")) {
      if (key.includes("any.")) {
        //but any.contains is our special case
        must.push({
          simple_query_string: {
            query: value,
            default_operator: "and",
          },
        });
      } else {
        must.push({
          match: {
            [field]: {
              query: value,
              fuzziness: "AUTO",
              operator: "AND",
            },
          },
        });
      }
    }

    //.contains queries are ES 'term's
    if (key.includes(".equals")) {
      //use ES terms
      must.push({
        term: {
          [field]: value,
        },
      });
    }

    if (key.includes(".in")) {
      //use ES terms
      if (value) {
        const stringified = value.toString().replace(",", " ");

        if (key.includes("any.")) {
          must.push({
            simple_query_string: {
              query: value,
              default_operator: "or",
            },
          });
        } else {
          must.push({
            match: {
              [field]: {
                query: stringified,
                operator: "OR",
              },
            },
          });
        }
      }
    }

    // "than" queries are ES range queries"
    if (key.includes("Than")) {
      //use ES range
      let op;
      if (key.includes("greaterThanOrEqual")) {
        op = "gte";
      } else {
        op = "lte";
      }

      must.push({
        range: {
          [field]: {
            [op]: value,
          },
        },
      });
    }

    if (key.includes("custom.glutenFree")) {
      if (value === true || value === "true") {
        must.push({
          simple_query_string: {
            query: '"gluten free"',
            default_operator: "and",
          },
        });
      } else {
        must.push({
          simple_query_string: {
            query: '-("gluten free")',
            default_operator: "and",
          },
        });
      }
    }

    if (key.includes("custom.grainFree")) {
      if (value === true || value === "true") {
        must.push({
          simple_query_string: {
            query: '"grain free"',
            default_operator: "and",
          },
        });
      } else {
        must.push({
          simple_query_string: {
            query: '-("grain free")',
            default_operator: "and",
          },
        });
      }
    }
  }

  if (must.length != 0) {
    requestBody.query = queryObj;
  }

  return requestBody;
};

不过(我认为)这里明显的潜在问题是注入攻击。真的我应该使用 ElasticSearch 库来进行查询,但它可能会很棘手,所以我想知道清理任何值的正确方法是什么?

标签: elasticsearch

解决方案


推荐阅读