System.InvalidOperationException:没有配置身份验证处理程序来处理方案:自动

System.InvalidOperationException: No authentication handler is configured to handle the scheme: Automatic

场景:

  1. 创建一个新的 Asp.Net 核心(版本 1.0.0)项目
  2. 选择 Web API 模板
  3. 在默认 ValuesController
  4. 上添加 [Authorize] 属性
  5. 运行 申请

如果我 运行 使用 IIS 的应用程序并向 http://localhost:60513/api/values 发出 GET 请求,我会得到预期的 401 Unauthorized error

但是,如果我 运行 使用 Kestrel 的应用程序(例如:dotnet run)并向 http://localhost:5000/api/values 发出 GET 请求,我会得到 500 Internal Server Error,但出现以下异常红隼:

Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[1]
      Request starting HTTP/1.1 GET http://localhost:5000/api/values
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2]
      Authorization failed for user: .
warn: Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker[1]
      Authorization failed for the request at filter 'Microsoft.AspNetCore.Mvc.Authorization.AuthorizeFilter'.
info: Microsoft.AspNetCore.Mvc.ChallengeResult[1]
      Executing ChallengeResult with authentication schemes ().
fail: Microsoft.AspNetCore.Server.Kestrel[13]
      Connection id "0HKUMMBBBQ6AU": An unhandled exception was thrown by the application.
System.InvalidOperationException: No authentication handler is configured to handle the scheme: Automatic
   at Microsoft.AspNetCore.Http.Authentication.Internal.DefaultAuthenticationManager.<ChallengeAsync>d__12.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   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.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeResultAsync>d__32.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Mvc.Internal.ControllerActionInvoker.<InvokeAsync>d__18.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   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.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Hosting.Internal.RequestServicesContainerMiddleware.<Invoke>d__3.MoveNext()
--- End of stack trace from previous location where exception was thrown ---
   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
   at Microsoft.AspNetCore.Server.Kestrel.Internal.Http.Frame`1.<RequestProcessingAsync>d__2.MoveNext()
info: Microsoft.AspNetCore.Hosting.Internal.WebHost[2]
      Request finished in 282.8427ms 200

我的问题是 为什么我的应用程序根据托管它的服务器有不同的结果?为什么 Kestrel 和 IIS 以不同方式处理授权?

请注意,Whosebug 中也有类似的问题,例如 or ,但它们都是针对涉及过滤器或中间件的更复杂的场景。

除了 MVC,我在 AspNet 管道中没有任何中间件,除了 [Authorize] 属性之外的所有代码都是由 AspNet Web Api 模板自动生成的。

根据 AspNet Security 中的 this thread,任何操作或控制器上的授权属性都需要管道中至少有一个身份验证中间件才能发出质询。 使用 IIS 时,会使用 IIS 中间件,但使用 Kestrel 时,没有处理此问题的 auth 中间件,因此我们需要添加自己的中间件。