首页 > Web开发 > 详细

ASP.NET Core-过滤器

时间:2020-05-22 09:10:37      阅读:284      评论:0      收藏:0      [点我收藏+]
原文: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));}
);

 

 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即可

 

 

 

未完待续...

ASP.NET Core-过滤器

原文:https://www.cnblogs.com/lonelyxmas/p/12934570.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!