解析Azure搜索查询过滤器



我的服务器作为用户搜索请求的代理。在Azure上请求数据之前,我们需要确保一切都是安全的。为此,我们将某些过滤器添加到查询过滤器中。假设我的服务器接收到以下查询:

search=&$top=10&$filter=customer/customerId gt 1 and customer/customerId lt 5

我想把它拆开,一块一块地研究它的过滤器,然后注入一个安全过滤器。

我要做的第一件事就是得到过滤器:

var parsed = HttpUtility.ParseQueryString(query);
var filter = parsed["$filter"];

接下来,我想对其进行处理,以便进行验证和更改。读了这篇文章后,我试图利用ODataUriParser如下:

// 1. Create a dummy model 
public static IEdmModel GetEdmModel()
{
var model = new EdmModel();
EdmEntityType customer = new EdmEntityType("Namespace", "Customer");
customer.AddKeys(customer.AddStructuralProperty("CustomerId", EdmPrimitiveTypeKind.Int32));
model.AddElement(customer);
return model;
}

// 2. Utilize it
static void Foo()
{
var query = "search=&$top=5001&$filter=Customer/CustomerId eq 1";

var parsed = HttpUtility.ParseQueryString(query);
var filter = parsed["$filter"];
var result = new ODataUriParser(HardCodedTestModel.TestModel, new Uri(filter, UriKind.Relative));
var parsedFilter = result.ParseFilter();
}

这会给我抛出一个异常,说:

未处理的例外。microsoft . odata . uriparser . odataunrecognizedpatheexception:资源不存在查找段"Customer">

  1. 我做错了什么?
  2. 是否有更简单的方法来实现我想要的?

您的EDM模型似乎不包括实体集,因此不清楚过滤器正在过滤什么。Azure Cognitive Search为每个索引定义了一个EDM模型,其中包括一个实体集"文档",其类型对应于索引定义。过滤器中的属性路径Customer/CustomerId将被Azure认知搜索解释为顶级Edm.ComplexType字段CustomerCustomerId子字段(使用OData术语,文档是实体,Customer是复杂属性,CustomerIdCustomer的属性)。如果您想使用ODataUriParserODataQueryOptionParser从过滤文本中获得语义AST,那么您的EDM模型必须包含所有这些模式信息。

也就是说,您可能不需要一个完整的语义AST来验证过滤器表达式的安全性(假设您正在尝试防御注入攻击之类的攻击)。单独使用OData筛选器解析器的词法阶段可能更简单。然后可以处理语法AST。

如果你想要最大程度的控制,你总是可以滚动你自己的解析器。OData的完整BNF在这里。

相关内容

  • 没有找到相关文章