过滤器

简介

5种过滤器如下:

AuthenticationFilter:执行方法前调用,实现对请求的验证,继承自IAuthenticationFilter接口

AuthorizationFilter:执行方法前调用,完成针对当前请求的授权检查,继承IAuthorizationFilter接口

ActionFilter:注册回调操作会在执行方法前后调用,继承自IActionFilter接口

ExceptionFilter:方法在执行中抛出异常,对异常进行处理,继承自IExceptionFilter接口

OverrideFilter:屏蔽Filter默认的功能,继承自IOverrideFilter接口

 

过滤器范围

全局,控制器,方法

    public enum FilterScope
    {
        First,
        Global = 10,
        Controller = 20,
        Action = 30,
        Last = 100
    }

测试代码A

    [Foo]
    public class DefaultController : ApiController
    {
        [Bar]
        [Baz]
        public IEnumerable<Tuple<string, FilterScope>> Get()
        {
            IHttpActionSelector actionSelector = this.Configuration.Services.GetActionSelector();
            HttpActionDescriptor actionDescriptor = actionSelector.SelectAction(this.ControllerContext);
            foreach(FilterInfo filterInfo in actionDescriptor.GetFilterPipeline())
            {
                yield return new Tuple<string, FilterScope>(filterInfo.Instance.GetType().Name,filterInfo.Scope);
            }
        }
    }

    public class FooAttribute:ActionFilterAttribute { }
    public class BarAttribute : ActionFilterAttribute { }
    public class BazAttribute : ActionFilterAttribute { }
    public class QuxAttribute : ActionFilterAttribute { }

Global.asax

    public class WebApiApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            GlobalConfiguration.Configuration.Filters.Add(new QuxAttribute());
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }
    }

 测试代码B

为了使用唯一的筛选器,可以设置AllowMultiple = false,优先级为Action->Controller->Global

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]

 

    public class DemoController : ApiController
    {
        public IEnumerable<Tuple<string, string, FilterScope>> Get()
        {
            HttpControllerDescriptor[] controllerDescriptors = new HttpControllerDescriptor[] { 
            new HttpControllerDescriptor(this.Configuration,"foo",typeof(FooController)),
            new HttpControllerDescriptor(this.Configuration,"bar",typeof(BarController)),
            new HttpControllerDescriptor(this.Configuration,"baz",typeof(BazController)),
        };

            IHttpActionSelector actionSelector = this.Configuration.Services.GetActionSelector();
            IEnumerable<HttpActionDescriptor> actionDescriptors = controllerDescriptors.SelectMany(controllerDescriptor =>
                actionSelector.GetActionMapping(controllerDescriptor)["Action"]);
            foreach (HttpActionDescriptor actionDescriptor in actionDescriptors)
            {
                foreach (FilterInfo filterInfo in actionDescriptor.GetFilterPipeline())
                {
                    yield return new Tuple<string, string, FilterScope>(
                            string.Format("{0}.{1}", actionDescriptor.ControllerDescriptor.ControllerType.Name, actionDescriptor.ActionName),
                            filterInfo.Instance.GetType().Name,
                            filterInfo.Scope);
                }
            }
        }
    }

    [Authenticate]
    public class FooController : ApiController
    {

        [Authenticate]
        public void Action()
        { }
    }

    [Authenticate]
    public class BarController : ApiController
    {
        public void Action()
        { }
    }

    public class BazController : ApiController
    {
        public void Action()
        { }
    }

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = false)]
    public class AuthenticateAttribute : FilterAttribute, IAuthenticationFilter
    {
        public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            return Task.Factory.StartNew(() => { });
        }

        public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            return Task.Factory.StartNew(() => { });
        }
    }

Global.asax

   protected void Application_Start()
        {
            GlobalConfiguration.Configuration.Filters.Add(new AuthenticateAttribute());
            GlobalConfiguration.Configure(WebApiConfig.Register);
        }

 AuthenticationFilter

用户认证

GenericIdentity 为一般性身份
GenericPrincipal可以理解为身份+角色
ChallengeAsync认证失败后向客户端发出质询


  [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthenticateAttribute : FilterAttribute, IAuthenticationFilter
    {
        private static Dictionary<string, string> userAccounters;
        static AuthenticateAttribute()
        {
            userAccounters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            userAccounters.Add("Foo","Password");
            userAccounters.Add("Bar","Password");
            userAccounters.Add("Baz","Password");
        }
        public Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            IPrincipal user = null;
            AuthenticationHeaderValue headerValue = context.Request.Headers.Authorization;
            if(null != headerValue && headerValue.Scheme == "Basic")
            {
                string credential = Encoding.Default.GetString(Convert.FromBase64String(headerValue.Parameter));
                string[] split = credential.Split(':');
                if(split.Length == 2)
                {
                    string userName = split[0];
                    string password;
                    if(userAccounters.TryGetValue(userName, out password))
                    {
                        if(password == split[1])
                        {
                            GenericIdentity identity = new GenericIdentity(userName);
                            user = new GenericPrincipal(identity,new string[0]);
                        }
                    }

                }
            }
            context.Principal = user;
            return Task.FromResult<object>(null);
        }

        public Task ChallengeAsync(HttpAuthenticationChallengeContext context, CancellationToken cancellationToken)
        {
            IPrincipal user = context.ActionContext.RequestContext.Principal;
            if(null == user || !user.Identity.IsAuthenticated)
            {
                string parameter = string.Format("realm = \"{0}\"",context.Request.RequestUri.DnsSafeHost);
                AuthenticationHeaderValue headerValue = new AuthenticationHeaderValue("Basic",parameter);
                context.Result = new UnauthorizedResult(new AuthenticationHeaderValue[] { headerValue},context.Request);
            }
            return Task.FromResult<object>(null);
        }
    }
    [Authenticate]
    public class DefaultController : ApiController
    {  
        public string Get()
        {
            return "成功调用";
        }
    }

客户端调用

        static void Main(string[] args)
        {
            HttpClient client = new HttpClient();
            HttpResponseMessage response = client.GetAsync("http://localhost:8089/api/default").Result;
            if(response.StatusCode == HttpStatusCode.Unauthorized)
            {
                Console.WriteLine("认证失败");
                AuthenticationHeaderValue headerValue = response.Headers.WwwAuthenticate.FirstOrDefault();
                if(headerValue != null && headerValue.Scheme == "Basic")
                {
                    Console.Write("用户名:");
                    string userName = Console.ReadLine().Trim();
                    Console.Write("密码:");
                    string password = Console.ReadLine().Trim();
                    byte[] credentical = Encoding.Default.GetBytes(string.Format("{0}:{1}",userName,password));
                    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic",Convert.ToBase64String(credentical));
                    response = client.GetAsync("http://localhost:8089/api/default").Result;
                    var result =  response.Content.ReadAsStringAsync().Result;
                    Console.WriteLine(result);

                }
            }
            Console.ReadLine();
            
        }

AuthorizationFilter

    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
    public class AuthenticateAttribute : AuthorizationFilterAttribute
    {
        private static Dictionary<string, string> userAccounters;
        static AuthenticateAttribute()
        {
            userAccounters = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
            userAccounters.Add("Foo", "Password");
            userAccounters.Add("Bar", "Password");
            userAccounters.Add("Baz", "Password");
        }

        public override void OnAuthorization(HttpActionContext actionContext)
        {
            AuthenticationHeaderValue headerValue = actionContext.Request.Headers.Authorization;
            if (null != headerValue && headerValue.Scheme == "Basic")
            {
                string credential = Encoding.Default.GetString(Convert.FromBase64String(headerValue.Parameter));
                string[] split = credential.Split(':');
                if (split.Length == 2)
                {
                    string userName = split[0];
                    string password;
                    if (userAccounters.TryGetValue(userName, out password))
                    {
                        if (password == split[1])
                        {
                            GenericIdentity identity = new GenericIdentity(userName);
                            actionContext.ControllerContext.RequestContext.Principal = new GenericPrincipal(identity, new string[0]);
                            return;
                        }
                    }
                }
            }
            HttpResponseMessage response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized);
            string parameter = string.Format("realm=\"{0}\"", actionContext.Request.RequestUri.DnsSafeHost);
            AuthenticationHeaderValue challenge = new AuthenticationHeaderValue("Basic", parameter);
            response.Headers.WwwAuthenticate.Add(challenge);
            actionContext.Response = response;
        }
    }

 

posted @ 2020-03-17 11:21  bradleydan  阅读(116)  评论(0)    收藏  举报