C# .net core 2.1 Authorization异常处理
C# .net core 2.1 Exception handling of Authorization
所以在 Web API 2 in .net framework 4.7.1 如果你有一个处理异常的过滤器,定义如下:
public sealed class RequestExceptionFilter : ExceptionFilterAttribute..
并且在 WebApiConfig 中:
config.Filters.Add(new MyAuthorizationFilter());
config.Filters.Add(new RequestExceptionFilter());
如果在 MyAuthorizationFilter
中发生任何异常,它将在 RequestExceptionFilter
中被捕获。
在 .net core 2.1 中,我有以下内容:
services.AddMvc(options =>
{
options.Filters.Add(new MyExceptionFilter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddAuthentication("Basic").AddScheme<AuthenticationSchemeOptions, UserAuthenticator>("Basic", null)
// configure DI for application services
services.AddScoped<IUserAuthenticator, UserAuthenticatorHandler>();
我有以下处理程序:
public sealed class UserAuthenticator: AuthenticationHandler<AuthenticationSchemeOptions>
现在,如果我在 protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
中抛出异常,这是 UserAuthenticator
的方法,服务器 returns 内部服务器错误并跳过异常处理。
我可以让它传播到异常过滤器吗?
根据 https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.1 看来授权过滤器 运行 在异常过滤器之前。
也许如果您将异常处理从过滤器中移至添加为中间件
在public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
方法中:
app.UseMiddleware<MyErrorHandling>();
public class MyErrorHandling
{
private readonly RequestDelegate _next;
public MyErrorHandling(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception e)
{
// Do stuff?
await context.Response.WriteAsync("it broke. :(");
}
}
}
我认为这种方法比使用过滤器更灵活。
像这样创建一个扩展方法
public static void UseGlobalExceptionHandler(this IApplicationBuilder appBuilder, ILogger logger)
{
appBuilder.UseExceptionHandler(app =>
{
app.Run(async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";
var ex = context.Features.Get<IExceptionHandlerFeature>()?.Error;
//AuthException is your custom exception class
if (ex != null && ex.GetType() == typeof(AuthException))
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync("Unautherized");
}
});
});
}
在配置方法下的startup.cs文件中使用它
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//Use it like this
app.UseGlobalExceptionHandler();
}
在.net core中很多过滤器(尤其是全局过滤器)的功能已经被Middleware所取代。
MVC 中过滤器的执行顺序由框架固定 - MSDN Link
在 .net 核心中,中间件按照
中配置的顺序执行
Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
Startup.cs
中的方法
这意味着如果您的中间件出现异常,您的授权过滤器将无法工作。解决此问题的最佳方法是将异常处理移至中间件,并确保在该方法中首先或几乎首先添加它。
另一种选择是启用开发人员例外页面进行测试。
我已经在这个 SO 答案中更详细地回答了如何:
所以在 Web API 2 in .net framework 4.7.1 如果你有一个处理异常的过滤器,定义如下:
public sealed class RequestExceptionFilter : ExceptionFilterAttribute..
并且在 WebApiConfig 中:
config.Filters.Add(new MyAuthorizationFilter());
config.Filters.Add(new RequestExceptionFilter());
如果在 MyAuthorizationFilter
中发生任何异常,它将在 RequestExceptionFilter
中被捕获。
在 .net core 2.1 中,我有以下内容:
services.AddMvc(options =>
{
options.Filters.Add(new MyExceptionFilter());
}).SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
services.AddAuthentication("Basic").AddScheme<AuthenticationSchemeOptions, UserAuthenticator>("Basic", null)
// configure DI for application services
services.AddScoped<IUserAuthenticator, UserAuthenticatorHandler>();
我有以下处理程序:
public sealed class UserAuthenticator: AuthenticationHandler<AuthenticationSchemeOptions>
现在,如果我在 protected override async Task<AuthenticateResult> HandleAuthenticateAsync()
中抛出异常,这是 UserAuthenticator
的方法,服务器 returns 内部服务器错误并跳过异常处理。
我可以让它传播到异常过滤器吗?
根据 https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.1 看来授权过滤器 运行 在异常过滤器之前。
也许如果您将异常处理从过滤器中移至添加为中间件
在public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory)
方法中:
app.UseMiddleware<MyErrorHandling>();
public class MyErrorHandling
{
private readonly RequestDelegate _next;
public MyErrorHandling(RequestDelegate next)
{
_next = next;
}
public async Task Invoke(HttpContext context)
{
try
{
await _next.Invoke(context);
}
catch (Exception e)
{
// Do stuff?
await context.Response.WriteAsync("it broke. :(");
}
}
}
我认为这种方法比使用过滤器更灵活。
像这样创建一个扩展方法
public static void UseGlobalExceptionHandler(this IApplicationBuilder appBuilder, ILogger logger)
{
appBuilder.UseExceptionHandler(app =>
{
app.Run(async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.ContentType = "application/json";
var ex = context.Features.Get<IExceptionHandlerFeature>()?.Error;
//AuthException is your custom exception class
if (ex != null && ex.GetType() == typeof(AuthException))
{
context.Response.StatusCode = (int)HttpStatusCode.Unauthorized;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync("Unautherized");
}
});
});
}
在配置方法下的startup.cs文件中使用它
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
//Use it like this
app.UseGlobalExceptionHandler();
}
在.net core中很多过滤器(尤其是全局过滤器)的功能已经被Middleware所取代。
MVC 中过滤器的执行顺序由框架固定 - MSDN Link
在 .net 核心中,中间件按照
中配置的顺序执行Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
Startup.cs
这意味着如果您的中间件出现异常,您的授权过滤器将无法工作。解决此问题的最佳方法是将异常处理移至中间件,并确保在该方法中首先或几乎首先添加它。
另一种选择是启用开发人员例外页面进行测试。
我已经在这个 SO 答案中更详细地回答了如何: