Технический стек следующим образом
- Ядро .Net WebApi (C#)
- МаркЛогик 9.0.8.2
Мы разработали MarkLogic API с базовой аутентификацией, и при вызове его из C# WebApi мы передаем учетные данные в заголовке.
Мы заметили, что в журналах доступа 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= правда HTTP/1.1" 200 44229 - -
Тот же запрос идет с 401, т.е. неавторизованным, а затем сразу с 200, т.е. успешным.
Мы поняли, что вызов конечной точки API из C# WebAPI — это предварительный запрос с ОПЦИЯМИ перед вызовом фактического запроса.
Мы обнаружили, что для решения этой проблемы есть возможность отправить тип контента как «текстовый/обычный», но мы не можем этого сделать, поскольку у нас есть объект JSON, а затем нам нужно сделать больше, чтобы проанализировать текст в объект JSON.
Когда мы звоним из PostMan, мы сталкиваемся с той же проблемой.
Из-за этого, когда у нас есть множество запросов к API, ML API возвращает ошибку 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
}
}
);