过滤器接口:
授权过滤器:IAuthorizationFilter、IAsyncAuthorizationFilter(AuthorizeFilter)
通常用于验证请求合法性
资源过滤器:IResourceFilter、IAsyncResourceFilter
资源过滤器在过滤器管道中第二个被执行,通常用于请求结果的缓存和短路过滤器管道。与Action过滤器的区别是资源过滤器在Controller创建之间就执行了
Action过滤器:IActionFilter、IAsyncActionFilter
通常用于校验Action参数
异常过滤器:IExceptionFilter、IAsyncExceptionFilter
异常信息处理
Result过滤器:IResultFilter、IAsyncResultFilter
通常用于对执行结果格式化处理
Core2.0添加全局过滤器:
services.AddMvc(o =>
{o.Filters.Add(typeof(CustomerResourceFilterAttribute));}
);
在过滤器中注入服务:
如果需要在过滤器中注入服务,需要修改构造函数,但是代码编译不过,提示缺少参数。
使用TypeFilter和ServiceFilter都可以解决过滤器注入问题,使用方法如下:
使用TypeFilter,直接将 [CustomerActionFilter] 替换为 [TypeFilter(typeof(CustomerActionFilterAttribute))] 即可
使用ServiceFilter,将 [CustomerActionFilter] 替换为 [ServiceFilter(typeof(TestServiceFilter))] 。然后注册过滤器 services.AddSingleton<CustomerActionFilterAttribute>();
ResourceFilter:
和ActionFilter的区别是:OnResourceExecuting在Controller创建之前调用,OnResourceExecuted最后执行
public class CustomerResourceFilterAttribute : Attribute, IResourceFilter
{
private static ConcurrentDictionary<string, object> CACHE_DICT = new ConcurrentDictionary<string, object>();
private string _cacheKey;
public void OnResourceExecuting(ResourceExecutingContext context)
{
_cacheKey = context.HttpContext.Request.Path.ToString();
if (CACHE_DICT.TryGetValue(_cacheKey, out object result))
{
var actionResult = result as IActionResult;
if (actionResult != null)
{
context.Result = actionResult;
}
}
}
public void OnResourceExecuted(ResourceExecutedContext context)
{
if (!CACHE_DICT.ContainsKey(_cacheKey))
{
if (context.Result != null)
{
CACHE_DICT.TryAdd(_cacheKey, context.Result);
}
}
}
}
ActionFilter:
public class CustomerActionFilterAttribute : Attribute, IActionFilter
{
public void OnActionExecuting(ActionExecutingContext context)
{
Console.WriteLine("OnActionExecuting");
}
public void OnActionExecuted(ActionExecutedContext context)
{
Console.WriteLine("OnActionExecuted");
}
}
ResultFilter:
public class CustomerResultFilterAttribute : Attribute, IResultFilter
{
public void OnResultExecuting(ResultExecutingContext context)
{
Console.WriteLine("OnResultExecuting");
}
public void OnResultExecuted(ResultExecutedContext context)
{
Console.WriteLine("OnResultExecuted");
}
}
ExceptionFilter:
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
private readonly IHostingEnvironment _hostingEnvironment;
private readonly IModelMetadataProvider _modelMetadataProvider;
public CustomExceptionFilterAttribute(
IHostingEnvironment hostingEnvironment,
IModelMetadataProvider modelMetadataProvider)
{
_hostingEnvironment = hostingEnvironment;
_modelMetadataProvider = modelMetadataProvider;
}
public override void OnException(ExceptionContext filterContext)
{
if (!filterContext.ExceptionHandled)//异常有没有被处理过
{
string controllerName = (string)filterContext.RouteData.Values["controller"];
string actionName = (string)filterContext.RouteData.Values["action"];
if (this.isAjaxRequest(filterContext.HttpContext.Request))//检查请求头
{
filterContext.Result = new JsonResult(
new AjaxResult()
{
Result = DoResult.Failed,
PromptMsg = "系统出现异常,请联系管理员",
DebugMessage = filterContext.Exception.Message
}//这个就是返回的结果
);
}
else
{
var result = new ViewResult { ViewName = "~/Views/Shared/Error.cshtml" };
result.ViewData = new ViewDataDictionary(_modelMetadataProvider, filterContext.ModelState);
result.ViewData.Add("Exception", filterContext.Exception);
filterContext.Result = result;
}
filterContext.ExceptionHandled = true;
}
}
private bool isAjaxRequest(HttpRequest request)
{
string header = request.Headers["X-Requested-With"];
return "XMLHttpRequest".Equals(header);
}
}
AuthorizeFilter:
public class PermissionAuthorizeFilter : AuthorizeFilter { public PermissionAuthorizeFilter(AuthorizationPolicy policy) : base(policy) { } public override Task OnAuthorizationAsync(AuthorizationFilterContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } bool isAuth = false; HttpContext httpContext = context.HttpContext; ClaimsPrincipal user = httpContext.User; if (user.Identity.IsAuthenticated) { int userID = Convert.ToInt32(user.Identities.First(u => u.IsAuthenticated) .FindFirst(ClaimTypes.NameIdentifier).Value); string[] permissions = null; string path = httpContext.Request.Path; var actionDescriptor = (Microsoft.AspNetCore.Mvc.Controllers.ControllerActionDescriptor) context.ActionDescriptor; var allowanyone = actionDescriptor.ControllerTypeInfo.GetCustomAttributes(typeof(IAllowAnonymous), true) .Any() || actionDescriptor.MethodInfo.GetCustomAttributes(typeof(IAllowAnonymous), true) .Any(); //是否允许匿名访问 if (allowanyone) { isAuth = true; } else { permissions = new string[] {path}; isAuth = this.IsAuth(httpContext, userID, permissions); } if (!isAuth) { context.Result = (IActionResult) new ForbidResult(CookieAuthenticationDefaults.AuthenticationScheme); } return Task.CompletedTask; } else { return base.OnAuthorizationAsync(context); } } /// <summary> /// 判断用户是否有权限 /// </summary> /// <param name="httpContext"></param> /// <param name="userID"></param> /// <param name="permissions"></param> /// <returns></returns> private bool IsAuth(HttpContext httpContext,int userID,string[] permissions) { bool isAuth = false; //从容器里面取出来注入的对象 var valueProvider = httpContext.RequestServices.GetService<IGlobalValueProvider>(); var accountPermissionService = httpContext.RequestServices.GetService<IAccountPermissionService>(); var userPermissions = accountPermissionService.GetUserPermissions(userID, valueProvider.SystemSite.ID); foreach (var permission in userPermissions) { if (!string.IsNullOrEmpty(permissions.FirstOrDefault(p => permission.Href.Equals(p, StringComparison.CurrentCultureIgnoreCase)))) { isAuth = true; break; } } return isAuth; } }
案例1:使用过滤器实现JsonP功能

public class JsonpFilter : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { } public void OnActionExecuted(ActionExecutedContext context) { // do something after the action executes //if (context.HttpContext.Request.Headers.FirstOrDefault(x => x.Key == "X-Requested-With").Value == "XMLHttpRequest") //{ // context.Result = new JsonpResult(new JsonResult(context.Exception), context.HttpContext.Request.Query["callback"]); // return; //} if (context.Exception != null || context.Result == null || !(context.Result is JsonResult)) return; if (context.HttpContext.Request.Method != "GET") return; if (string.IsNullOrEmpty(context.HttpContext.Request.Query["callback"])) return; context.Result = new JsonpResult(context.Result as JsonResult, context.HttpContext.Request.Query["callback"]); } public class JsonpResult : ActionResult { private static readonly string DefaultContentType = new MediaTypeHeaderValue("application/json") { CharSet = "utf-8" }.ToString(); private readonly JsonResult result = null; private readonly string callback; public JsonpResult(JsonResult p, string callback) { result = p; this.callback = callback; } public override Task ExecuteResultAsync(ActionContext context) { if (result == null) { throw new ArgumentNullException(nameof(result)); } if (context == null) { throw new ArgumentNullException(nameof(context)); } var services = context.HttpContext.RequestServices; var Options = services.GetRequiredService<IOptions<MvcJsonOptions>>().Value; var writerFactory = services.GetRequiredService<IHttpResponseStreamWriterFactory>(); var _charPool = new JsonArrayPool<char>(services.GetRequiredService<ArrayPool<char>>()); var response = context.HttpContext.Response; ResponseContentTypeHelper.ResolveContentTypeAndEncoding( result.ContentType, response.ContentType, DefaultContentType, out var resolvedContentType, out var resolvedContentTypeEncoding); response.ContentType = resolvedContentType; if (result.StatusCode != null) { response.StatusCode = result.StatusCode.Value; } var serializerSettings = result.SerializerSettings ?? Options.SerializerSettings; using (var writer = writerFactory.CreateWriter(response.Body, resolvedContentTypeEncoding)) { var jsonSerializer = JsonSerializer.Create(serializerSettings); using (var jsonWriter = new JsonTextWriter(writer)) { jsonWriter.ArrayPool = _charPool; jsonWriter.CloseOutput = false; jsonWriter.AutoCompleteOnClose = false; jsonWriter.WriteRaw(callback + "("); jsonSerializer.Serialize(jsonWriter, result.Value); jsonWriter.WriteRaw(");"); } } return Task.CompletedTask; } } }
添加全局过滤器
services.AddMvc(o => { o.Filters.Add(typeof(JsonpFilter)); }
在http请求中 url带上参数callback即可
未完待续...