过滤器
简介
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; } }

浙公网安备 33010602011771号