针对自定义statscode的需求,我们需要重写ABP框架的两个默认过滤器
1,授权过滤器
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/// <summary> /// 权限验证过滤器 /// </summary> public class AuthorizationFilter : IAsyncAuthorizationFilter, ITransientDependency { /// <summary> /// /// </summary> public ILogger Logger { get; set; } private readonly IAuthorizationHelper _authorizationHelper; private readonly IErrorInfoBuilder _errorInfoBuilder; private readonly IEventBus _eventBus; /// <summary> /// 构造函数 /// </summary> /// <param name="authorizationHelper"></param> /// <param name="errorInfoBuilder"></param> /// <param name="eventBus"></param> public AuthorizationFilter( IAuthorizationHelper authorizationHelper, IErrorInfoBuilder errorInfoBuilder, IEventBus eventBus) { _authorizationHelper = authorizationHelper; _errorInfoBuilder = errorInfoBuilder; _eventBus = eventBus; Logger = NullLogger.Instance; } /// <summary> /// 权限验证 /// </summary> /// <param name="context"></param> /// <returns></returns> public async Task OnAuthorizationAsync(AuthorizationFilterContext context) { // Allow Anonymous skips all authorization if (context.Filters.Any(item => item is IAllowAnonymousFilter)) { return; } if (!context.ActionDescriptor.IsControllerAction()) { return; } //TODO: Avoid using try/catch, use conditional checking try { await _authorizationHelper.AuthorizeAsync( context.ActionDescriptor.GetMethodInfo(), context.ActionDescriptor.GetMethodInfo().DeclaringType ); } catch (AbpAuthorizationException ex) { Logger.Warn(ex.ToString(), ex); _eventBus.Trigger(this, new AbpHandledExceptionData(ex)); if (ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType)) { var er = _errorInfoBuilder.BuildForException(ex); // 使用结果包装器的code作为自定义状态编码 er.Code = context.HttpContext.User.Identity.IsAuthenticated ? (int)System.Net.HttpStatusCode.Forbidden : (int)System.Net.HttpStatusCode.Unauthorized; //将response状态码统一返回为200 context.Result = new ObjectResult(new AjaxResponse(er, true)) { StatusCode = (int)System.Net.HttpStatusCode.OK }; } else { context.Result = new ChallengeResult(); } } catch (Exception ex) { Logger.Error(ex.ToString(), ex); _eventBus.Trigger(this, new AbpHandledExceptionData(ex)); if (ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType)) { var er = _errorInfoBuilder.BuildForException(ex); er.Code = (int)System.Net.HttpStatusCode.InternalServerError; context.Result = new ObjectResult(new AjaxResponse(er)) { StatusCode = (int)System.Net.HttpStatusCode.OK }; } else { context.Result = new StatusCodeResult((int)System.Net.HttpStatusCode.InternalServerError); } } } }
2,异常过滤器
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
/// <summary> /// /// </summary> public class ExceptionFilter : IExceptionFilter, ITransientDependency { /// <summary> /// /// </summary> public ILogger Logger { get; set; } /// <summary> /// /// </summary> public IEventBus EventBus { get; set; } private readonly IErrorInfoBuilder _errorInfoBuilder; private readonly IAbpAspNetCoreConfiguration _configuration; /// <summary> /// /// </summary> /// <param name="errorInfoBuilder"></param> /// <param name="configuration"></param> public ExceptionFilter(IErrorInfoBuilder errorInfoBuilder, IAbpAspNetCoreConfiguration configuration) { _errorInfoBuilder = errorInfoBuilder; _configuration = configuration; Logger = NullLogger.Instance; EventBus = NullEventBus.Instance; } /// <summary> /// /// </summary> /// <param name="context"></param> public void OnException(ExceptionContext context) { if (!context.ActionDescriptor.IsControllerAction()) { return; } var wrapResultAttribute = ReflectionHelper.GetSingleAttributeOfMemberOrDeclaringTypeOrDefault( context.ActionDescriptor.GetMethodInfo(), _configuration.DefaultWrapResultAttribute ); if (wrapResultAttribute.LogError) { LogHelper.LogException(Logger, context.Exception); } if (wrapResultAttribute.WrapOnError) { HandleAndWrapException(context); } } /// <summary> /// /// </summary> /// <param name="context"></param> private void HandleAndWrapException(ExceptionContext context) { if (!ActionResultHelper.IsObjectResult(context.ActionDescriptor.GetMethodInfo().ReturnType)) { return; } context.HttpContext.Response.StatusCode = (int)HttpStatusCode.OK; var errorInfo = _errorInfoBuilder.BuildForException(context.Exception); errorInfo.Code = GetStatusCode(context,errorInfo); context.Result = new ObjectResult( new AjaxResponse( errorInfo, context.Exception is AbpAuthorizationException ) ); EventBus.Trigger(this, new AbpHandledExceptionData(context.Exception)); context.Exception = null; //Handled! } /// <summary> /// /// </summary> /// <param name="context"></param> /// <param name="errorInfo"></param> /// <returns></returns> protected virtual int GetStatusCode(ExceptionContext context, ErrorInfo errorInfo) { if (context.Exception is AbpAuthorizationException) { return context.HttpContext.User.Identity.IsAuthenticated ? (int)HttpStatusCode.Forbidden : (int)HttpStatusCode.Unauthorized; } if (context.Exception is AbpValidationException) { return (int)HttpStatusCode.BadRequest; } if (context.Exception is EntityNotFoundException) { return (int)HttpStatusCode.NotFound; } if(context.Exception is UserFriendlyException) { return errorInfo.Code; } return (int)HttpStatusCode.InternalServerError; } }
3,在statup文件中注册重写的过滤器
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
// MVC services.AddMvc( options => { options.Filters.Add(new CorsAuthorizationFilterFactory(_defaultCorsPolicyName)); options.Filters.AddService(typeof(AuthorizationFilter), order: 0); options.Filters.AddService(typeof(ExceptionFilter), order: 2); } );
注意代码中的的数字,测试发现如果不加入手动排序,ioc容器会把重写的过滤器置于次要地位,过滤器会不起作用
4,在ioc容器中注册这两个过滤器,我偷懒就都写在statup中了
![](https://i-blog.csdnimg.cn/blog_migrate/8f900a89c6347c561fdf2122f13be562.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/961ddebeb323a10fe0623af514929fc1.gif)
// Configure Abp and Dependency Injection return services.AddAbp<MarketManageWebHostModule>( options => { options.IocManager.IocContainer.AddFacility<LoggingFacility>( f => f.UseAbpLog4Net().WithConfig("log4net.config") ); options.IocManager.Register<IExceptionFilter, ExceptionFilter>(Abp.Dependency.DependencyLifeStyle.Transient); options.IocManager.Register<IAsyncAuthorizationFilter, AuthorizationFilter>(Abp.Dependency.DependencyLifeStyle.Transient); } );