如何禁用从 C# WebApi 到 MarkLogic 服务器的预检请求
How to disable preflight request to MarkLogic server from C# WebApi
技术栈如下
- .Net核心WebApi (C#)
- 马克逻辑 9.0.8.2
我们开发了带有基本身份验证的 MarkLogic API,在从 C# WebApi 调用它时,我们在 header 中传递凭据。
我们注意到 MarkLogic 访问日志有 2 个条目,即
- xx.xxx.xxx.xx - - [18/May/2020:06:05:35 +0000] "GET /getcontent?query=test&offset=1&size=10&format=Extended&sortOrder=ASC&transform=&IncludeFacet=true HTTP/1.1" 401 209 - -
- xx.xxx.xxx.xx - MLUser [18/May/2020:06:05:35 +0000] "GET /getcontent?query=test&offset=1&size=10&format=Extended&sortOrder=ASC&transform=&IncludeFacet=true HTTP/1.1" 200 44229 - -
同样的请求返回 401,即未授权,然后立即返回 200,即成功。
我们意识到从 C# WebAPI 调用 API 端点是在调用实际请求之前使用 OPTIONS 进行预检请求。
我们发现可以选择将内容类型发送为 'text/plain' 来解决这个问题,但我们不能,因为我们有 JSON object 然后我们需要做更多将文本解析为 JSON object.
当我们从 PostMan 调用时,我们面临着同样的问题。
因此,当我们在 API 上有大量请求时,ML API returns 在防火墙上出现 401 错误,然后 FW 阻止所有请求,将其视为暴力攻击.
有什么办法可以禁用预检请求调用吗?
MarkLogicHttpClient _client;
var queryParams = new Dictionary<string, string>
{
{ "query", searchRequest.Query },
{ "offset", searchRequest.Offset.ToString() },
{ "size", searchRequest.Size.ToString() },
{ "format", searchRequest.Format },
{ "sortOrder", searchRequest.SortOrder.ToString().ToUpper() },
{ "transform", transform }
};
var searchUri = QueryHelpers.AddQueryString("getcontent", queryParams);
var response = await _client.GetAsync(searchUri);
//Startup.cs
services.AddHttpClient<IMarkLogicClient, MarkLogicHttpClient>(client =>
{
client.BaseAddress = MarkLogicEndpoint;
})
.ConfigurePrimaryHttpMessageHandler(() =>
new HttpClientHandler
{
Credentials = new NetworkCredential
{
UserName = UserName,
Password = Password
}
}
);
HttpClient 仅在首次从服务器收到带有 WWW-Authenticate header 的 401 响应后才发送授权 header。
默认情况下,HttpClient 在授权每个 请求之前等待 401 响应。
有两种方法可以减少 401 响应的数量。
设置HttpClientHandler.PreAuthenticate
属性
services.AddHttpClient<IMarkLogicClient, MarkLogicHttpClient>(client =>
{
client.BaseAddress = MarkLogicEndpoint;
})
.ConfigurePrimaryHttpMessageHandler(() =>
new HttpClientHandler
{
// cache the WWW-Authenticate response and send Authorize header
// on all subsequent requests
PreAuthenticate = true,
Credentials = new NetworkCredential
{
UserName = UserName,
Password = Password
}
});
或者,手动添加 Authorize Header 到 HttpClient.DefaultRequestHeaders
services.AddHttpClient<IMarkLogicClient, MarkLogicHttpClient>(client =>
{
// construct HTTP Basic Authorization header and send on every request
// Do not add credentials to HttpClientHandler
var authorization= "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(Username + ":" + Password));
client.BaseAddress = MarkLogicEndpoint;
client.DefaultRequestHeaders.Add("Authorization", authorization);
});
技术栈如下
- .Net核心WebApi (C#)
- 马克逻辑 9.0.8.2
我们开发了带有基本身份验证的 MarkLogic API,在从 C# WebApi 调用它时,我们在 header 中传递凭据。
我们注意到 MarkLogic 访问日志有 2 个条目,即
- xx.xxx.xxx.xx - - [18/May/2020:06:05:35 +0000] "GET /getcontent?query=test&offset=1&size=10&format=Extended&sortOrder=ASC&transform=&IncludeFacet=true HTTP/1.1" 401 209 - -
- xx.xxx.xxx.xx - MLUser [18/May/2020:06:05:35 +0000] "GET /getcontent?query=test&offset=1&size=10&format=Extended&sortOrder=ASC&transform=&IncludeFacet=true HTTP/1.1" 200 44229 - -
同样的请求返回 401,即未授权,然后立即返回 200,即成功。
我们意识到从 C# WebAPI 调用 API 端点是在调用实际请求之前使用 OPTIONS 进行预检请求。
我们发现可以选择将内容类型发送为 'text/plain' 来解决这个问题,但我们不能,因为我们有 JSON object 然后我们需要做更多将文本解析为 JSON object.
当我们从 PostMan 调用时,我们面临着同样的问题。
因此,当我们在 API 上有大量请求时,ML API returns 在防火墙上出现 401 错误,然后 FW 阻止所有请求,将其视为暴力攻击.
有什么办法可以禁用预检请求调用吗?
MarkLogicHttpClient _client;
var queryParams = new Dictionary<string, string>
{
{ "query", searchRequest.Query },
{ "offset", searchRequest.Offset.ToString() },
{ "size", searchRequest.Size.ToString() },
{ "format", searchRequest.Format },
{ "sortOrder", searchRequest.SortOrder.ToString().ToUpper() },
{ "transform", transform }
};
var searchUri = QueryHelpers.AddQueryString("getcontent", queryParams);
var response = await _client.GetAsync(searchUri);
//Startup.cs
services.AddHttpClient<IMarkLogicClient, MarkLogicHttpClient>(client =>
{
client.BaseAddress = MarkLogicEndpoint;
})
.ConfigurePrimaryHttpMessageHandler(() =>
new HttpClientHandler
{
Credentials = new NetworkCredential
{
UserName = UserName,
Password = Password
}
}
);
HttpClient 仅在首次从服务器收到带有 WWW-Authenticate header 的 401 响应后才发送授权 header。
默认情况下,HttpClient 在授权每个 请求之前等待 401 响应。
有两种方法可以减少 401 响应的数量。
设置HttpClientHandler.PreAuthenticate
属性
services.AddHttpClient<IMarkLogicClient, MarkLogicHttpClient>(client =>
{
client.BaseAddress = MarkLogicEndpoint;
})
.ConfigurePrimaryHttpMessageHandler(() =>
new HttpClientHandler
{
// cache the WWW-Authenticate response and send Authorize header
// on all subsequent requests
PreAuthenticate = true,
Credentials = new NetworkCredential
{
UserName = UserName,
Password = Password
}
});
或者,手动添加 Authorize Header 到 HttpClient.DefaultRequestHeaders
services.AddHttpClient<IMarkLogicClient, MarkLogicHttpClient>(client =>
{
// construct HTTP Basic Authorization header and send on every request
// Do not add credentials to HttpClientHandler
var authorization= "Basic " + Convert.ToBase64String(Encoding.UTF8.GetBytes(Username + ":" + Password));
client.BaseAddress = MarkLogicEndpoint;
client.DefaultRequestHeaders.Add("Authorization", authorization);
});