一、WebAPI自定义过滤器的使用

一、WebAPI自定义过滤器的使用

1、注册过滤器

using System.Web.Http;
using KYINT.WebAPIService.Handler;

namespace KYINT.WebAPIService
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API 配置和服务

            // Web API 路由
            config.MapHttpAttributeRoutes();

            config.Routes.MapHttpRoute(
                 name: "ActionApi",
                 routeTemplate: "{controller}/{action}/{id}",
                 defaults: new { id = RouteParameter.Optional }
             );

            //移除XML格式,采用Json进行数据交互
            config.Formatters.XmlFormatter.SupportedMediaTypes.Clear();

            //处理DateTime类型序列化后含有T的问题
            config.Formatters.JsonFormatter.SerializerSettings.Converters.Insert(0, new JsonDateTimeConverter());

            //添加全局异常处理器
            config.Filters.Add(new KYExceptionFilter());

            //添加全局认证过滤器
            config.Filters.Add(new KYAuthenticationFilter());

            //添加全局统计过滤器
            config.Filters.Add(new StatisticsFilter());
        }
    }
}

2、全局认证过滤器

    /// <summary>
    /// 认证过滤器,验证是否含有UUID标头
    /// </summary>
    public class KYAuthenticationFilter : Attribute, IAuthenticationFilter
    {
        public async Task AuthenticateAsync(HttpAuthenticationContext context, CancellationToken cancellationToken)
        {
            if (KYAuthenticationFilter.SkipAuthentication(context))
            {
                return ;
            }

            IPrincipal principal = await this.AuthenticateAsync(context.Request);
            if (principal == null)
            {
                context.ErrorResult = new AuthenticationFailureResult("未授权请求", context.Request);
            }
            else
            {
                context.Principal = principal;
            }
        }

/// <summary> /// 从授权表头中取出授权值并验证,验证通过构建正确的Principal对象 /// </summary> /// <param name="request"></param> /// <returns></returns> private Task<IPrincipal> AuthenticateAsync(HttpRequestMessage request) { return Task.Run<IPrincipal>(() => { string UUID = request.GetHeader("UUID"); if (string.IsNullOrWhiteSpace(UUID)) { return null; } User user = TB_NUsersBLL.GetUser(UUID); if (user == null) { return null; } request.Properties.Add("UUID", user); IEnumerable<Claim> claims = new List<Claim>() { new Claim(ClaimTypes.Sid, UUID), new Claim(ClaimTypes.Name, user.UserName), new Claim(ClaimTypes.MobilePhone, user.TelePhone) }; return new ClaimsPrincipal(new ClaimsIdentity(claims)); }); } /// <summary> /// 检查控制器或方法是否启用NoAuthenticationAttribute,如果启用了,则跳过认证 /// </summary> /// <param name="context"></param> /// <returns></returns> private static bool SkipAuthentication(HttpAuthenticationContext context) { return context.ActionContext.ActionDescriptor.GetCustomAttributes<NoAuthenticationAttribute>().Any<NoAuthenticationAttribute>() || context.ActionContext.ControllerContext.ControllerDescriptor.GetCustomAttributes<NoAuthenticationAttribute>().Any<NoAuthenticationAttribute>(); } }

2.1、不需鉴权过滤器

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = false)]
    public sealed class NoAuthenticationAttribute : Attribute
    {
    }

 

3、全局统计过滤器

    /// <summary>
    /// 全局统计过滤器
    /// </summary>
    public class StatisticsFilter : ActionFilterAttribute
    {
        public override void OnActionExecuting(HttpActionContext actionContext)
        {
            base.OnActionExecuting(actionContext);
            //以下为业务处理
            string methodName = actionContext.Request.RequestUri.AbsolutePath;
            //异步调用
            Task.Factory.StartNew((obj) => TA_InteriorAppModuleInfoBLL.AddModuleInfo((string)obj), methodName);
        }
    }

 4、全局异常过滤器

    /// <summary>
    /// 全局异常过滤器
    /// </summary>
    public class KYExceptionFilter : ExceptionFilterAttribute
    {
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            #region 标准做法

            //var exception = actionExecutedContext.Exception;

            //if (exception is BusinessException)     //业务异常,一般不需记录日志,直接反馈错误信息至前端
            //{
            //    actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse((HttpStatusCode)exception.HResult, new HttpError(exception.Message));
            //}
            //else        //未处理异常如数据库访问出错、代码层面异常等,返回错误信息并记录日志
            //{
            //    actionExecutedContext.Response = actionExecutedContext.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, new HttpError(exception.Message));
            //    //LogHelper.Error(typeof(KYExceptionFilter), exception);
            //    LogHelper.Error(actionExecutedContext.Request.RequestUri.AbsolutePath, exception);
            //}

            #endregion

            #region 变异做法(受限于现在接口及各终端通行做法,后期需要调整为标准做法)

            var exception = actionExecutedContext.Exception;

            if (exception is BusinessException)     //业务异常,一般不需记录日志,直接反馈错误信息至前端
            {
                actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(HttpStatusCode.OK, Utils.AssembleMsg(exception.Message));
            }
            else if (exception is OperationCanceledException)//ThirdParty/GetMobilePlace 处理已取消该操作异常
            {
                actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(HttpStatusCode.OK, Utils.AssembleMsg("客户端取消了这次请求"));
            }
            else        //未处理异常如数据库访问出错、代码层面异常等,返回错误信息并记录日志
            {
                actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(HttpStatusCode.OK, Utils.AssembleMsg("服务器处理出错"));
                LogHelper.Error(typeof(KYExceptionFilter), actionExecutedContext.Request.RequestUri.AbsolutePath, exception);
            }

            #endregion
        }
    }

 

posted @ 2018-08-02 14:47  woadmin  阅读(559)  评论(0编辑  收藏  举报