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

时间:2016-09-07 00:11:59

标签: iis asp.net-core asp.net-core-mvc authorize-attribute kestrel-http-server

情景:

  1. 创建一个新的Asp.Net Core(版本1.0.0)项目
  2. 选择Web API模板
  3. 在默认的ValuesController
  4. 上添加[Authorize]属性
  5. 运行应用程序
  6. 如果我使用IIS运行应用程序并向http://localhost:60513/api/values发出GET请求,我会得到预期的401 Unauthorized error

    但是,如果我使用Kestrel运行应用程序(例如:dotnet run)并向http://localhost:5000/api/values发出GET请求,我会在kestrel处获得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以不同的方式处理授权?

    请注意,StackOverflow中存在类似问题,例如thisthis other,但它们都适用于涉及过滤器或中间件的更复杂情况。

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

1 个答案:

答案 0 :(得分:2)

根据AspNet Security中的this thread,任何操作或控制器上的Authorize属性都需要管道中至少有一个auth中间件才能发出挑战。 当使用IIS时,使用了IIS中间件,但是当使用Kestrel时,没有auth中间件处理这个,因此我们需要添加自己的。