码迷,mamicode.com
首页 > Windows程序 > 详细

C# WebApi 过滤器的使用开发接口必备利器

时间:2018-05-26 16:37:49      阅读:278      评论:0      收藏:0      [点我收藏+]

标签:cep   and   逻辑   public   开发   nts   ken   用户名   并且   

在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理。引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想,通过Filter能统一地对一些通用逻辑进行处理,如:权限校验、参数加解密、参数校验等方面我们都可以利用这一特性进行统一处理,今天我们来介绍Filter的开发、使用以及讨论他们的执行顺序。

一、Filter的开发和调用

         在默认的WebApi中,框架提供了三种Filter,他们的功能和运行条件如下表所示:

Filter 类型

实现的接口

描述

Authorization

IAuthorizationFilter

最先运行的Filter,被用作请求权限校验

Action

IActionFilter

在Action运行的前、后运行

Exception

IExceptionFilter

当异常发生的时候运行

       首先,我们实现一个AuthFilterOutside可以用以简单的权限控制:

 public class AuthFilterOutside: AuthorizeAttribute
    {
        private SP_PortUserBLL sp_portuserbll = new SP_PortUserBLL();
        //重写基类的验证方式,加入我们自定义的Ticket验证  
        public override void OnAuthorization(HttpActionContext actionContext)
        {
            //url获取token  
            var content = actionContext.Request.Properties["MS_HttpContext"] as HttpContextBase;
            HttpRequestBase request = content.Request;
            string access_key = request.Form["access_key"];//获取请求参数对应的值
            string sign = request.Form["sign"];
            if (!string.IsNullOrEmpty(access_key) && !string.IsNullOrEmpty(sign))
            {
                //解密用户ticket,并校验用户名密码是否匹配  
                if (ValidateTicket(access_key, sign))
                {
                    base.IsAuthorized(actionContext);
                }
                else
                {
                    HandleUnauthorizedRequest(actionContext);
                }
            }
            //如果取不到身份验证信息,并且不允许匿名访问,则返回未验证401
            else
            {
                var attributes = actionContext.ActionDescriptor.GetCustomAttributes<AllowAnonymousAttribute>().OfType<AllowAnonymousAttribute>();
                bool isAnonymous = attributes.Any(a => a is AllowAnonymousAttribute);
                if (isAnonymous) base.OnAuthorization(actionContext);
                else HandleUnauthorizedRequest(actionContext);
            }
        }
        //校验sign(数据库数据匹配)  
        private bool ValidateTicket(string key,string sign)
        {
            var result=sp_portuserbll.GetAccess_secret(key);
            if (!string.IsNullOrEmpty(result))
            {
                var mysing= Encryption.DataEncryption(key, result);//sign验证
                if (mysing.Equals(sign))
                {
                    return true;
                }
                return false;
            }
            return false;
        }
    }

  当请求地址里面包含  access_key 和  sign  对应的键值对,获取对应的值与数据库数据进行匹配,匹配通过后可请求数据,适用于get 、post请求。

 

接口请求成功后记录日志的实现

 /// <summary>
    /// 请求成功后触发
    /// </summary>
    public class AuthFilter: ActionFilterAttribute
    {
        private PortLogBLL portlogbll = new PortLogBLL();
        public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
        {
            //action 请求之后触发
//日志记录 访问量记录等等 portlogbll.SaveForm(new PortLogEntity() { PortName = actionExecutedContext.Request.RequestUri.AbsolutePath,//获得调用接口, RequestType = actionExecutedContext.Request.Method.ToString(), StatusCode = Convert.ToInt32(new HttpResponseMessage(HttpStatusCode.OK).StatusCode),//设置状态码 ClientIp = GetClientIp(), ParameterList = actionExecutedContext.ActionContext.ActionArguments.ToJson(),//获得参数值 Success = true }); } /// <summary> /// 获取客户端Ip /// </summary> /// <returns></returns> private string GetClientIp() { string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; } if (string.IsNullOrEmpty(result)) { result = HttpContext.Current.Request.UserHostAddress; } if (string.IsNullOrEmpty(result)) { return "0.0.0.0"; } return result; } }

  

当服务端代码报错或出异常时,可自定义设置固定格式的异常返回给调用者

 /// <summary>
    /// 接口发生异常过滤器
    /// </summary>
    public class ExceptionHandling : ExceptionFilterAttribute, IExceptionFilter
    {
        private PortLogBLL portlogbll = new PortLogBLL();
        public override void OnException(HttpActionExecutedContext actionExecutedContext)
        {
            var code = new HttpResponseMessage(HttpStatusCode.InternalServerError).StatusCode;//设置错误代码:例如:500 404
            actionExecutedContext.Response = new HttpResponseMessage(HttpStatusCode.InternalServerError);
            string msg = JsonConvert.SerializeObject(new BaseResult() { success = false, message = actionExecutedContext.Exception.Message });//返回异常错误提示
                                                                                                                                              //写入错误日志相关实现
            portlogbll.SaveForm(new PortLogEntity()
            {
                PortName = actionExecutedContext.Request.RequestUri.AbsolutePath,
                RequestType = actionExecutedContext.Request.Method.ToString(),
                StatusCode = Convert.ToInt32(code),
                ClientIp = GetClientIp(),
                ParameterList = actionExecutedContext.ActionContext.ActionArguments.ToJson(),
                Success = false,
                ErrorMessage = msg
            });
            //result
            actionExecutedContext.Response.Content = new StringContent(msg, Encoding.UTF8);
        }
        /// <summary>
        /// 获取调用接口者ip地址
        /// </summary>
        /// <returns></returns>
        private string GetClientIp()
        {
            string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            if (string.IsNullOrEmpty(result))
            {
                result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            }
            if (string.IsNullOrEmpty(result))
            {
                result = HttpContext.Current.Request.UserHostAddress;
            }
            if (string.IsNullOrEmpty(result))
            {
                return "0.0.0.0";
            }
            return result;
        }
    }
    public class BaseResult
    {
        /// <summary>
        /// 状态
        /// </summary>
        public bool success { get; set; }
        /// <summary>
        /// 错误信息
        /// </summary>
        public string message { get; set; }
    }

  

以上是开发webapi常用代码,自己封装一下就可以使用了

C# WebApi 过滤器的使用开发接口必备利器

标签:cep   and   逻辑   public   开发   nts   ken   用户名   并且   

原文地址:https://www.cnblogs.com/jiangxifanzhouyudu/p/9093147.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!