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

一、Filter的使用

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

Filter 类型

实现的接口

描述

Authorization

IAuthorizationFilter

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

Action

IActionFilter

在Action运行的前、后运行

Exception

IExceptionFilter

当异常发生的时候运行

1.授权拦截过滤器

首先,我们实现一个CustomAuthorizeAttribute可以用以简单的权限控制,(此处AuthorizeAttribute继承自AuthorizationFilterAttribute)用于接口授权:

/// <summary>
/// 自定义授权
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomAuthorizeAttribute:AuthorizeAttribute
{
/// <summary>
/// 用户授权
/// </summary>
/// <param name="actionContext"></param>
/// <returns></returns>
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.Params["access_key"];//不管是post请求还是get请求,都从地址栏获取key跟sign
string sign = request.Params["sign"];
//校验IP
var data=XmlUtil.IsAuthorization(HttpContext.Current.Request.UserHostAddress);
if (data.IsExistence)//ip是否在白名单内
{
if ("".Equals(data.IsAuthorization))//是否需要参与签名验证
{
if (!string.IsNullOrEmpty(access_key) && !string.IsNullOrEmpty(sign))
{
var key = "7058e63cdf0646948201";//随便固定一个key,真实使用的化可以从数据库获取或配置文件读取
var s = MD5Encrypt32(string.Format("{0}{1}", access_key, key));
if ("2c3a368b-26a8-4a4d-a204-14bd6388f3c2".Equals(access_key) && s.Equals(sign))//验证通过放行
{
base.IsAuthorized(actionContext);
}
else
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new
{
code = HttpStatusCode.Unauthorized,
data = "",
message = "access_key 或 sign 参数有误,请核对",
});
}
}
else
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new
{
code = HttpStatusCode.Unauthorized,
data = "",
message = "access_key 或 sign 校验参数未从地址栏带入,请核对",
});
}
}
else
{
base.IsAuthorized(actionContext);
}
}
else
{
actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, new
{
code = HttpStatusCode.Unauthorized,
data = "",
message = $"IP:{HttpContext.Current.Request.UserHostAddress}没有调用服务的权限",
});
}
}
/// <summary>
/// 32位MD5加密
/// </summary>
/// <param name="password"></param>
/// <returns></returns>
public string MD5Encrypt32(string password)
{
string pwd = "";
MD5 md5 = MD5.Create(); //实例化一个md5对像
// 加密后是一个字节类型的数组,这里要注意编码UTF8/Unicode等的选择 
byte[] s = md5.ComputeHash(Encoding.UTF8.GetBytes(password));
// 通过使用循环,将字节类型的数组转换为字符串,此字符串是常规字符格式化所得
for (int i = ; i < s.Length; i++)
{
// 将得到的字符串使用十六进制类型格式。格式后的字符是小写的字母,如果使用大写(X)则格式后的字符是大写字符
pwd = pwd + s[i].ToString("X");
}
return pwd.ToLower();
}
}

2.错误异常捕获过滤器

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

/// <summary>
/// 自定义错误异常捕获
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomExceptionAttribute:ExceptionFilterAttribute
{
/// <summary>
/// 异常发生
/// </summary>
/// <param name="actionExecutedContext"></param>
public override void OnException(HttpActionExecutedContext actionExecutedContext)
{
//记录错误日志
Task.Run(() =>
{
//此处可以调用记录日志方法
});
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(HttpStatusCode.InternalServerError, new
{
code = HttpStatusCode.InternalServerError,
message = actionExecutedContext.Exception.Message
});
}
}

3.请求成功过滤器

如果要把所有接口返回类型参数固定可以使用ActionFilter过滤器,简单实现如下:

/// <summary>
/// 自定义统一信息格式返回
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method)]
public class CustomActionAttribute:ActionFilterAttribute
{
/// <summary>
/// 请求成功之后
/// </summary>
/// <param name="actionExecutedContext"></param>
public override void OnActionExecuted(HttpActionExecutedContext actionExecutedContext)
{
actionExecutedContext.Response = actionExecutedContext.Request.CreateResponse(actionExecutedContext.Response.StatusCode, new
{
code = ,
data =JsonConvert.DeserializeObject(actionExecutedContext.Response.Content.ReadAsStringAsync().Result),//返回给调用者的数据
message ="success"
});
}
}

接口调用成功之后返回给调用者的数据格式都是固定格式,调用者使用起来就很方便,返回固定格式如下:

{
code = ,
data ="数据"
message ="success"
}

二、过滤器的使用及注册

过滤器注册方式有三种:

  • 全局注册
  • 类注册
  • 方法注册

1.全局注册

全局注册时在App_Start==>WebApiConfig.cs文件里面,注册代码如下:

public static class WebApiConfig
{
/// <summary>
///
/// </summary>
/// <param name="config"></param>
public static void Register(HttpConfiguration config)
{
// 身份认证筛选器。
config.Filters.Add(new CustomAuthorizeAttribute());//这是全局注册 config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
); config.EnsureInitialized();
}
}

2.控制器注册

控制器注册就是在Controller类里面进行注册,注册代码如下:

/// <summary>
///
/// </summary>
[CustomAuthorizeAttribute] //控制器注册
public class DepartmentApiController : ApiController { }

3.方法注册

方法注册就是在Controller里面使用的方法上进行标记注册,注册代码如下:

/// <summary>
///
/// </summary>
public class DepartmentApiController : ApiController { [CustomAuthorizeAttribute]//方法注册
[HttpGet]
public object GetDepartmentList()
{ }
}

三、过滤器执行优先级

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method,AllowMultiple = false)]//AllowMultiple=false时 执行优先级如下

同一个过滤器分别用在了全局、控制器和行为方法中,执行同一个方法时都会有先后顺序,如果按默认值(不设Order的情况下),一般的顺序是由最外层到最里层,就是“全局”——>“控制器”——>“行为方法”;

而特别的就是错误处理的过滤器,由于异常是由里往外抛的,所以它的顺序刚好也反过来:“行为方法”——>“控制器”——>“全局”。

以上是开发webapi过滤器的简单用法,以上代码还需要优化,有需要的朋友自己封装优化一下就可以使用了。

C# WebApi 过滤器的使用开发接口必备利器的更多相关文章

  1. C# WebApi过滤器(开发接口必备利器)

    在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理.引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想 ...

  2. C/C++服务器开发的必备利器–libconfig

    http://www.leoox.com/?p=311 程序肯定需要一份配置文件,要不然,自己的程序不是“可配置”的,自己都不好意思往“高大上”靠拢.言归正传,以前自己写代码,配置文件的读写都是各式各 ...

  3. MVC WebAPI 三层分布式框架开发

    版权声明:本文为博主原创文章,未经博主允许不得转载. 前言:SOA(面向服务的架构)是目前企业应用开发过程中普遍采用的技术,基于MVC WebAPI三层分布式框架开发,以此适用于企业信息系统的业务处理 ...

  4. Web 开发人员必备的随机 JSON 数据生成工具

    在 Web 开发中,经常会需要一些测试数据来测试接口或者功能时候正确.JSON Generator 就是这样一款生成随机 JSON 数据的在线工具,Web 开发人员必备,记得收藏和分享啊. 您可能感兴 ...

  5. 转载CSDN (MVC WebAPI 三层分布式框架开发)

    前言:SOA(面向服务的架构)是目前企业应用开发过程中普遍采用的技术,基于MVC WebAPI三层分布式框架开发,以此适用于企业信息系统的业务处理,是本文论述的重点.此外,插件技术的应用,富客户端JQ ...

  6. Android开发学习必备的java知识

    Android开发学习必备的java知识本讲内容:对象.标识符.关键字.变量.常量.字面值.基本数据类型.整数.浮点数.布尔型.字符型.赋值.注释 Java作为一门语言,必然有他的语法规则.学习编程语 ...

  7. Fiddler无所不能——之测试开发攻城狮必备利器

    Fiddler无所不能——之测试开发攻城狮必备利器 1.模拟真实网络环境4g网.3g网络.2g网络.弱网.请求超时 开启弱网Rules——Performance——勾选Simulate Modem S ...

  8. (转载)Android快速开发偷懒必备,一句话搞定所有ViewGroup的Adapter . 支持自定义ViewGroup

    [置顶] [Android]快速开发偷懒必备,一句话搞定所有ViewGroup的Adapter . 支持自定义ViewGroup 标签: androidAdapter快速开发0耦合 2016-12-1 ...

  9. ASP.NET Core WebApi基于Redis实现Token接口安全认证

    一.课程介绍 明人不说暗话,跟着阿笨一起玩WebApi!开发提供数据的WebApi服务,最重要的是数据的安全性.那么对于我们来说,如何确保数据的安全将会是需要思考的问题.在ASP.NET WebSer ...

随机推荐

  1. POJ1236学校网络——tarjan

    题目:http://poj.org/problem?id=1236 Tarjan+缩点.温习一下Tarjan的写法. 1.在缩点后的TAG中,有几个联通块等价于有几个入度为0的点! 2.把它们都联通相 ...

  2. Python的学习计划

    整体进度(6-7个月毕业)一.(2月左右)Python基础二.数据库(1-2周)---存储数据和信息(本质上和文件没有区别) 增删改查更方便了三.前端(2周左右)---html.css等等四.框架(2 ...

  3. URL的getFile()和getPath()方法的区别(转)

    转自博客:http://blog.csdn.net/l375852247/article/details/7999063 import java.net.MalformedURLException; ...

  4. Hive新功能 Cube, Rollup介绍

    说明:Hive之cube.rollup,还有窗口函数,在传统关系型数据(Oracle.sqlserver)中都是有的,用法都很相似. GROUPING SETS GROUPING SETS作为GROU ...

  5. VS2017如何配置openGL环境

    转自:http://blog.csdn.net/qq_26982531/article/details/62056913 这里着重介绍vs2017配置openGL环境与以前版本的不同之处:       ...

  6. istio 配置https gateway

    沒有親手實驗,参考官方文档:  https://istio.io/docs/tasks/traffic-management/secure-ingress/

  7. C++11新特性介绍 01

    阅读目录 1. 概述 2. long long 类型 3. 列表初始化 4. nullptr 空指针 5. constexpr变量 6. constexpr函数 7. using类型别名 8. aut ...

  8. 给iOS开发新手送点福利,简述UISwitch的属性和用法

    UISwitch属性 1. onTintColor 处于on时switch 的颜色     switchImage.onTintColor = [UIColor grayColor]; 2.tintC ...

  9. /proc目录下文件详解

    /proc “文件系统”是一个目录,其中包含的文件层次结构代表了 Linux 内核的当前状态.它允许用户和管理员查看系统的内核视图. /proc 目录中还包含关于系统硬件及任何当前正在运行的程序信息. ...

  10. 并发包学习(一)-Atomic包小记

    此篇是J.U.C学习的第一篇Atomic包相关的内容,希望此篇总结能对自己的基础有所提升.本文总结来源自<Java并发编程的艺术>第七章并配以自己的实践理解.如有错误还请指正. 一.案例分 ...