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作为一门语言,必然有他的语法规则.学习编程语 ...
随机推荐
- ES 6 系列 - Module 的语法
es 6 大幅度优化了模块化编程的规范. 写在前面:在 es6 之前,说起 js 的模块化,一般都避不开 CommonJs 和 AMD 两种方案.这两种方案,前者应用于服务器,后者应用于浏览器.而 e ...
- 学习 Spring (十四) Introduction
Spring入门篇 学习笔记 Introduction 允许一个切面声明一个实现指定接口的通知对象,并且提供了一个接口实现类来代表这些对象 由 中的 元素声明该元素用于声明所匹配的类型拥有一个新的 p ...
- gauss——seidel迭代
转载:https://blog.csdn.net/wangxiaojun911/article/details/6890282 Gauss–Seidelmethod 对应于形如Ax = b的方程(A为 ...
- 了解AutoCAD对象层次结构 —— 2 ——文档
再次想象另外一个场景:启动AutoCAD程序后,您新建了两个.dwg文件,也就是说创建了两个文档(Document)对象.将窗口进行层叠,您看到的窗口应该与下图类似: 图 4‑3 如何访问这些文档呢? ...
- POJ1442-查询第K大-Treap模板题
模板题,以后要学splay,大概看一下treap就好了. #include <cstdio> #include <algorithm> #include <cstring ...
- bzoj 1103 : [POI2007]大都市meg (树链剖分+线段树)
Description 在经济全球化浪潮的影响下,习惯于漫步在清晨的乡间小路的邮递员Blue Mary也开始骑着摩托车传递邮件了.不过,她经常回忆起以前在乡间漫步的情景.昔日,乡下有依次编号为1..n ...
- QML 用QSortFilterProxyModel实现搜索功能
搞了一晚上终于实现了,写个博客纪念一下吧. c++部分的代码: #include <QQmlApplicationEngine> #include <QQmlContext> ...
- bzoj4671: 异或图
bzoj4671: 异或图 Description 定义两个结点数相同的图 G1 与图 G2 的异或为一个新的图 G, 其中如果 (u, v) 在 G1 与 G2 中的出现次数之和为 1, 那么边 ( ...
- 自学华为IoT物联网_10 IoT联接管理平台配置及开发实验1
点击返回自学华为IoT物流网 自学华为IoT物联网_10 IoT联接管理平台配置及开发实验1 实验1:OceanConnect平台实验 通过基本的编程操作与配置,帮助读者熟悉O ...
- 【洛谷2252&HDU1527】取石子游戏(博弈论)
题面 HDU1527 取石子游戏 洛谷2252 取石子游戏 题解 裸的威佐夫博弈 #include<iostream> #include<cmath> using namesp ...