zoukankan      html  css  js  c++  java
  • ASP.NET Core-过滤器

    过滤器接口:

    授权过滤器: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;
                }
            }
        }
    View Code

    添加全局过滤器

    services.AddMvc(o =>
                {
                    o.Filters.Add(typeof(JsonpFilter));
                }

    在http请求中 url带上参数callback即可

    未完待续...

  • 相关阅读:
    堆和栈的区别
    MyKTV点歌系统
    KTV音乐播放的实现
    继承与多态之汽车租赁系统
    使用集合组织相关数据
    用户登陆及异常的处理
    oracle函数详解
    Java中的多线程
    JAVA Map集合框架的使用
    Java中迭代器初深
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/12144471.html
Copyright © 2011-2022 走看看