C# WebApi过滤器(开发接口必备利器)
在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过滤器(开发接口必备利器)的更多相关文章
- C# WebApi 过滤器的使用开发接口必备利器
在WEB Api中,引入了面向切面编程(AOP)的思想,在某些特定的位置可以插入特定的Filter进行过程拦截处理.引入了这一机制可以更好地践行DRY(Don’t Repeat Yourself)思想 ...
- C/C++服务器开发的必备利器–libconfig
http://www.leoox.com/?p=311 程序肯定需要一份配置文件,要不然,自己的程序不是“可配置”的,自己都不好意思往“高大上”靠拢.言归正传,以前自己写代码,配置文件的读写都是各式各 ...
- Fiddler无所不能——之测试开发攻城狮必备利器
Fiddler无所不能——之测试开发攻城狮必备利器 1.模拟真实网络环境4g网.3g网络.2g网络.弱网.请求超时 开启弱网Rules——Performance——勾选Simulate Modem S ...
- (转)Terraform,自动化配置与编排必备利器
本文来自作者 QingCloud实践课堂 在 GitChat 上分享 「Terraform,自动化配置与编排必备利器」 Terraform - Infrastructure as Code 什么是 T ...
- Web 开发人员必备的随机 JSON 数据生成工具
在 Web 开发中,经常会需要一些测试数据来测试接口或者功能时候正确.JSON Generator 就是这样一款生成随机 JSON 数据的在线工具,Web 开发人员必备,记得收藏和分享啊. 您可能感兴 ...
- Android开发工具综述,开发人员必备工具
安卓开发工具汇总.开发者必备.安卓开发过程中须要用到各种工具,作为一名安卓开发者,有木有感到亚历山大,那么多工具! 今天给大家汇总了一下安卓开发工具,安卓开发者必备利器. 1.Draw 9-Patch ...
- QuickWebApi2:使用Lambda方式,完成对WebApi的开发和调用-文档的生成
续 QuickWebApi:使用Lambda方式,完成对WebApi的开发和调用 上一篇完成了主要的功能,本次修订主要重构了对接口文档的生成规范,使之可读性更佳,甚至可以作为接口文档进行发布(当然,在 ...
- QuickWebApi:使用Lambada方式,完成对WebApi的开发和调用。
QuickWebApi 目的:使用Lambada方式,完成对WebApi的开发和调用. 缘由:为了解耦服务和展现,将越来越多的使用WebApi提供各种服务:随着服务的细化,WebApi的接口将越来越多 ...
- Android开发学习必备的java知识
Android开发学习必备的java知识本讲内容:对象.标识符.关键字.变量.常量.字面值.基本数据类型.整数.浮点数.布尔型.字符型.赋值.注释 Java作为一门语言,必然有他的语法规则.学习编程语 ...
随机推荐
- mvc HTML转Excel身份证后三位变成0
@{ var style = "vnd.ms-excel.numberformat:@"; } //HTML <td style=@style><span> ...
- [WC2018]州区划分——FWT+DP+FST
题目链接: [WC2018]州区划分 题目大意:给n个点的一个无向图,点有点权,要求将这n个点划分成若干个部分,每部分合法当且仅当这部分中所有点之间的边不能构成欧拉回路.对于一种划分方案,第i个部分的 ...
- BZOJ2616 SPOJ PERIODNI(笛卡尔树+树形dp)
考虑建一棵小根堆笛卡尔树,即每次在当前区间中找到最小值,以最小值为界分割区间,由当前最小值所在位置向两边区间最小值所在位置连边,递归建树.那么该笛卡尔树中的一棵子树对应序列的一个连续区间,且根的权值是 ...
- Balanced Number HDU - 3709 数位dp
题意: 给出范围 算出 满足 选取一个数中任一一个 树作为支点 两边的数分别乘以到中心的距离和 左和等于右和 的数有多少个 数位DP题 状态转移方程为dp[pos][x][state]=dp[ ...
- Codeforces1037F Maximum Reduction 【单调栈】
题目分析: 没啥好说的,会单调栈就会做. 代码: #include<bits/stdc++.h> using namespace std; ; ; int n,k; int pre[max ...
- 【XSY1262】【GDSOI2015】循环排插 斯特林数
题目描述 有一个\(n\)个元素的随机置换\(P\),求\(P\)分解出的轮换个数的\(m\)次方的期望\(\times n!\) \(n\leq 100000,m\leq 30\) 题解 解法一 有 ...
- bzoj 2733 : [HNOI2012]永无乡 (线段树合并)
Description 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示.某些岛之间由巨大的桥连接,通过桥可以 ...
- Windows10 + Visual Studio 2017环境为C++工程安装使用ZMQ
因为需要用 C++ 实现联机对战的功能,但是不想直接用 winsock ,因此选了ZMQ 框架(不知道合不合适).安装的过程还是挺艰辛的.但是也学到了些东西,记录一下.另外,Zmq 的作者 Piete ...
- 用keras实现基本的文本分类任务
数据集介绍 包含来自互联网电影数据库的50000条影评文本,对半拆分为训练集和测试集.训练集和测试集之间达成了平衡,意味着它们包含相同数量的正面和负面影评,每个样本都是一个整数数组,表示影评中的字词. ...
- 【agc013d】Piling Up(动态规划)
[agc013d]Piling Up(动态规划) 题面 atcoder 洛谷 有\(n\)个球,颜色为黑白中的一种,初始时颜色任意. 进行\(m\)次操作,每次操作都是先拿出一个求,再放进黑白各一个, ...