Фильтр авторизации .NET Core 2.0 вызывает внутреннюю ошибку

Фильтр авторизации вызовет внутреннюю ошибку в веб-приложении .NET Core 2.0. Действия по воспроизведению проблемы очень просты: создайте новый проект .NET Core 2.0 MVC без аутентификации, установите фильтр авторизации на метод контроллера, перейдите по соответствующему URL-адресу, и будет возвращено сообщение «500 Internal Server Error».

[Authorize]
public IActionResult Contact()
{
    ViewData["Message"] = "Your contact page.";

    return View();
}

Аналогичный код в .NET Core 1.1 будет правильно возвращать ответ «401 Unauthorized».

У меня был задан аналогичный вопрос по проблеме: Пользовательская аутентификация файлов cookie не работает после перехода с ASP.NET Core 1.1 MVC на 2.0, хотя я еще не понял, что проблема намного шире, чем в моем конкретном случае.

Исключение:

System.InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.
   at Microsoft.AspNetCore.Authentication.AuthenticationService.<ChallengeAsync>d__11.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.ChallengeResult.<ExecuteResultAsync>d__14.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeResultAsync>d__19.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeFilterPipelineAsync>d__17.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ResourceInvoker.<InvokeAsync>d__15.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Builder.RouterMiddleware.<Invoke>d__4.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.<Invoke>d__7.MoveNext()

person Marko    schedule 22.01.2018    source источник
comment
Запустим его под отладчиком, проверим логи, чтобы увидеть ошибку.   -  person Tratcher    schedule 22.01.2018
comment
Похоже, вы забыли добавить какие-либо соответствующие компоненты аутентификации в автозагрузку.   -  person Tratcher    schedule 22.01.2018
comment
Покажите нам хотя бы исключение, без него мы не имеем ни малейшего представления, что может быть не так   -  person Tseng    schedule 22.01.2018
comment
Аутентификация определяет, кем является пользователь, в противном случае он анонимен, и авторизация должна иметь дело с этим. В любом случае, даже если я аутентифицирую пользователя, произойдет та же ошибка.   -  person Marko    schedule 22.01.2018


Ответы (1)


HTTP 401 Неавторизованный ответ должен содержать WWW-Authenticate заголовок, определяющий метод аутентификации для доступа к ресурсу.

В вашем проекте, созданном без аутентификации, не установлена ​​какая-либо схема аутентификации по умолчанию. Вот почему промежуточное ПО для аутентификации не может сформировать действительный ответ 401 и вместо этого отправляет ошибку 500.

Исправить довольно просто. Добавьте любой обработчик аутентификации и установите схему аутентификации по умолчанию, например:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer();
}

При такой конфигурации неавторизованный запрос приведет к ответу 401 с правильно установленным заголовком WWW-Authenticate:

введите описание изображения здесь

person CodeFuller    schedule 23.01.2018
comment
Спасибо, может быть, вы можете взглянуть на этот вопрос, где действительно существует настраиваемая аутентификация. - person Marko; 23.01.2018