.NET Core 2.0 授权过滤器导致内部错误
.NET Core 2.0 Authorization filter causes an internal error
授权筛选器将导致 .NET Core 2.0 Web 应用程序出现内部错误。重现问题的步骤非常简单:使用 "no authentication" 创建一个新的 .NET Core 2.0 MVC 项目,在控制器方法上放置授权过滤器,访问相应的 URL 和“500 Internal Server Error”将 returned.
[Authorize]
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
.NET Core 1.1 中的类似代码将正确return 响应“401 Unauthorized”。
我就这个问题发布了一个类似的问题:Custom cookie authentication not working after migration from ASP.NET Core 1.1 MVC to 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()
HTTP 401 未经授权的响应 should contain WWW-Authenticate
header 定义了访问资源的身份验证方法。
在您未经身份验证创建的项目中,没有设置任何默认身份验证方案。这就是身份验证中间件无法构建有效的 401 响应并选择发送 500 错误的原因。
修复非常简单。添加任何身份验证处理程序并设置默认身份验证方案,例如:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer();
}
使用这样的配置,未经授权的请求将导致正确设置的 401 响应 WWW-Authenticate
header:
授权筛选器将导致 .NET Core 2.0 Web 应用程序出现内部错误。重现问题的步骤非常简单:使用 "no authentication" 创建一个新的 .NET Core 2.0 MVC 项目,在控制器方法上放置授权过滤器,访问相应的 URL 和“500 Internal Server Error”将 returned.
[Authorize]
public IActionResult Contact()
{
ViewData["Message"] = "Your contact page.";
return View();
}
.NET Core 1.1 中的类似代码将正确return 响应“401 Unauthorized”。
我就这个问题发布了一个类似的问题:Custom cookie authentication not working after migration from ASP.NET Core 1.1 MVC to 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()
HTTP 401 未经授权的响应 should contain WWW-Authenticate
header 定义了访问资源的身份验证方法。
在您未经身份验证创建的项目中,没有设置任何默认身份验证方案。这就是身份验证中间件无法构建有效的 401 响应并选择发送 500 错误的原因。
修复非常简单。添加任何身份验证处理程序并设置默认身份验证方案,例如:
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer();
}
使用这样的配置,未经授权的请求将导致正确设置的 401 响应 WWW-Authenticate
header: