在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 请求之后触发<br> //日志记录 访问量记录等等
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过滤器(开发接口必备利器)的更多相关文章

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

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

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

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

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

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

  4. (转)Terraform,自动化配置与编排必备利器

    本文来自作者 QingCloud实践课堂 在 GitChat 上分享 「Terraform,自动化配置与编排必备利器」 Terraform - Infrastructure as Code 什么是 T ...

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

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

  6. Android开发工具综述,开发人员必备工具

    安卓开发工具汇总.开发者必备.安卓开发过程中须要用到各种工具,作为一名安卓开发者,有木有感到亚历山大,那么多工具! 今天给大家汇总了一下安卓开发工具,安卓开发者必备利器. 1.Draw 9-Patch ...

  7. QuickWebApi2:使用Lambda方式,完成对WebApi的开发和调用-文档的生成

    续 QuickWebApi:使用Lambda方式,完成对WebApi的开发和调用 上一篇完成了主要的功能,本次修订主要重构了对接口文档的生成规范,使之可读性更佳,甚至可以作为接口文档进行发布(当然,在 ...

  8. QuickWebApi:使用Lambada方式,完成对WebApi的开发和调用。

    QuickWebApi 目的:使用Lambada方式,完成对WebApi的开发和调用. 缘由:为了解耦服务和展现,将越来越多的使用WebApi提供各种服务:随着服务的细化,WebApi的接口将越来越多 ...

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

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

随机推荐

  1. hdu-3068(最长回文子串-manacher)

    题意:求一个字符串#include<iostream>#include<algorithm>#include<cstring>using namespace std ...

  2. servlet篇 之 servlet概念及其功能实现

    Servlet概念: 在JavaWeb中,把那些可以使用浏览器通过url的形式来访问的java类,叫做servlet. servlet就是java类中的一种,只不过这种java类有一个特殊的功能,就是 ...

  3. mysql操作命令

    一.MySQL连接命令 mysql-u:指定用户-p:指定密码-S:指定socket文件-P:指定端口-h:指定主机域-e:指定sql语句 mysql> status \s 查看状态 mysql ...

  4. POJ 3322 Bloxorz(算竞进阶习题)

    bfs 标准广搜题,主要是把每一步可能的坐标都先预处理出来,会好写很多 每个状态对应三个限制条件,x坐标.y坐标.lie=0表示直立在(x,y),lie=1表示横着躺,左半边在(x,y),lie=2表 ...

  5. miller——rabin判断素数

    我们首先看这样一个很简单的问题:判定正整数\(n\)是否为素数 最简单的做法就是枚举\(2\)到\(n\)的所有数,看是否有数是\(n\)的因数,时间复杂度\(O(n)\) 稍微优化一下发现只要枚举\ ...

  6. 【XSY2760】nonintersect 计算几何

    题目描述 平面上有\(n\)条线段,你要擦掉所有线段但保留原有的\(2n\)个端点,然后连接这些端点形成\(n\)条不相交的线段,每个端点只能在一条线段中. 假设你画的线段总长为\(Y\),原有线段的 ...

  7. hdu 6253 (bfs打表)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=6253 题意: 马可以往一个方向走两步,然后转个弯走一步,这样算一次动作,求问马n次动作后,能到达多少个点, ...

  8. django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet.

    报错现象 django 启动的时候报错 django.core.exceptions.AppRegistryNotReady: Apps aren't loaded yet. 报错解决 记不清是我有毛 ...

  9. SPHINX 文档写作工具安装简要指南 - windows 版 - 基于python

    此教程基于本地己安装好 PYTHON 并配置过全局变量:一定具备相应的基础再操作: 上传图片以免产生误导,以下为文字描述,按下列操作即可: 下载 get-pip.py脚本; python get-pi ...

  10. 用webpack2.0构建vue2.0单文件组件超级详细精简实例

    npm init -y 初始化项目  //-y 为自动生成package.json,如果需要自行配置,去掉-y即可 安装各种依赖项 npm install --save vue 安装vue2.0 np ...