解析 Azure 搜索查询过滤器
Parse Azure search query filter
我的服务器充当用户搜索请求的代理。在 Azure 上请求数据之前,我们需要确保一切都是安全的。为此,我们将某些过滤器添加到查询过滤器中。
假设我的服务器收到此查询:
search=&$top=10&$filter=customer/customerId gt 1 and customer/customerId lt 5
我想拆开它,逐个研究它的过滤器并在其中注入安全过滤器。
我做的第一件事是获取过滤器:
var parsed = HttpUtility.ParseQueryString(query);
var filter = parsed["$filter"];
接下来,我要对其进行处理,以便验证和更改。
阅读 this post 后,我尝试像这样利用 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();
}
这对我抛出异常,说:
Unhandled exception.
Microsoft.OData.UriParser.ODataUnrecognizedPathException: Resource not
found for the segment 'Customer
- 我做错了什么?
- 有没有更简单的方法来实现我想要的?
您的 EDM 模型似乎不包含 entity set,因此不清楚过滤器在过滤什么。 Azure 认知搜索为每个包含实体集“docs”的索引定义了一个 EDM 模型,其类型对应于索引定义。 Azure 认知搜索会将筛选器中的 属性 路径 Customer/CustomerId
解释为名为 Customer
的顶级 Edm.ComplexType
字段的 CustomerId
子字段(使用 OData 术语,文档是实体,Customer
是一个 Complex 属性,而 CustomerId
是 Customer
的 属性)。如果您想使用 ODataUriParser
或 ODataQueryOptionParser
从过滤器文本中获取语义 AST,您的 EDM 模型将必须包含所有这些模式信息。
也就是说,您可能不需要完整的语义 AST 来验证过滤器表达式的安全性(假设您正在尝试抵御注入攻击之类的事情)。单独使用 OData 过滤器解析器的 lexical stage 可能更简单。然后就可以处理语法AST了。
如果您想要最大程度的控制,您可以随时推出自己的解析器。 OData 的完整 BNF 是 here.
我的服务器充当用户搜索请求的代理。在 Azure 上请求数据之前,我们需要确保一切都是安全的。为此,我们将某些过滤器添加到查询过滤器中。 假设我的服务器收到此查询:
search=&$top=10&$filter=customer/customerId gt 1 and customer/customerId lt 5
我想拆开它,逐个研究它的过滤器并在其中注入安全过滤器。
我做的第一件事是获取过滤器:
var parsed = HttpUtility.ParseQueryString(query);
var filter = parsed["$filter"];
接下来,我要对其进行处理,以便验证和更改。
阅读 this post 后,我尝试像这样利用 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();
}
这对我抛出异常,说:
Unhandled exception. Microsoft.OData.UriParser.ODataUnrecognizedPathException: Resource not found for the segment 'Customer
- 我做错了什么?
- 有没有更简单的方法来实现我想要的?
您的 EDM 模型似乎不包含 entity set,因此不清楚过滤器在过滤什么。 Azure 认知搜索为每个包含实体集“docs”的索引定义了一个 EDM 模型,其类型对应于索引定义。 Azure 认知搜索会将筛选器中的 属性 路径 Customer/CustomerId
解释为名为 Customer
的顶级 Edm.ComplexType
字段的 CustomerId
子字段(使用 OData 术语,文档是实体,Customer
是一个 Complex 属性,而 CustomerId
是 Customer
的 属性)。如果您想使用 ODataUriParser
或 ODataQueryOptionParser
从过滤器文本中获取语义 AST,您的 EDM 模型将必须包含所有这些模式信息。
也就是说,您可能不需要完整的语义 AST 来验证过滤器表达式的安全性(假设您正在尝试抵御注入攻击之类的事情)。单独使用 OData 过滤器解析器的 lexical stage 可能更简单。然后就可以处理语法AST了。
如果您想要最大程度的控制,您可以随时推出自己的解析器。 OData 的完整 BNF 是 here.