У меня есть обработчик авторизации, используемый для авторизации пользователей на моих сервисах. Если авторизация не удалась, я хочу написать собственный ответ непосредственно из промежуточного программного обеспечения авторизации, поэтому до сих пор я использовал этот фрагмент кода:
protected async Task SetUnauthorized(AuthorizationHandlerContext context, string json) {
_logger.LogInformation($"Authorization failed: {json}");
context.Fail();
_httpContextAccessor.HttpContext.Response.OnStarting(async () => {
_httpContextAccessor.HttpContext.Response.StatusCode = StatusCodes.Status401Unauthorized;
_httpContextAccessor.HttpContext.Response.ContentType = "application/json";
await _httpContextAccessor.HttpContext.Response.WriteAsync(json);
});
}
До сих пор у меня никогда не возникало проблем с этой реализацией, но когда я начал тестировать сбои в моих интеграционных тестах с xUnit, тесты неожиданно прерывались с переполнением стека. Используя Visual Studio для отладки моих тестов, я обнаружил, что ошибка переполнения стека вызвана бесконечным l oop, вызванным выполнением OnStarting()
при нажатии WriteAsync()
. Итак, как правильно реализовать это поведение, не вызывая переполнение стека?
Запустить журнал из Rider:
...
[16:26:06 INF] Executed action WebAPI.Controllers.v1.Client.TokenController.CreateToken (WebAPI) in 118.8913ms
[16:26:06 INF] Executed endpoint 'WebAPI.Controllers.v1.Client.TokenController.CreateToken (WebAPI)'
[16:26:06 INF] Request finished in 223.6489ms 400 application/json; charset=utf-8
[16:26:06 INF] Request starting HTTP/1.1 POST http://localhost/api/v1/client/token/token application/json; charset=utf-8
[16:26:06 INF] Authorization failed: {"code":"InvalidApplication","message":"Invalid Application Name or Application Secret."}
[16:26:06 INF] Authorization failed.
[16:26:06 INF] AuthenticationScheme: Bearer was challenged.
Stack overflow.
16:28:35.609 |E| Stack overflow exception occurred in test. Test run is aborted.
...