webapi接口安全验证
其实跟大多数网上的方法一样,在前端请求头里加token,后台通过拦截器处理token数据,然后两边对比,如果一样就能通过,不一样就返回无权限。
前端测试代码如下:
@{
ViewBag.Title = "TestApiAouth";
}
<h2>测试</h2>
<form id="form">
<div>
<label class="form-control">PIC:</label>
<input id="pic" type="file" name="pic" class="form-control" />
</div>
<div>
<button id="test" type="button">测试</button>
</div>
</form>
@section scripts{
<script src="~/Scripts/md5.js"></script>
<script>
$(function () {
$("#test").on("click", function () {
var id=$("#id").val();
var name = $("#name").val();
var add_arr = new Array();
add_arr.push("method=AddSkin");
add_arr.push("appcode=PHRASE");
add_arr.push("name=一叶孤舟");
add_arr.push("type=background");
add_arr.push("font_color=");
add_arr.push("price=7000");
add_arr.push("state=0");
add_arr.push("description=轻风无意助孤舟,任尔飘摇任尔游。");
add_arr.push("forever=1");
add_arr.push("sale_start=");
add_arr.push("sale_end=" );
add_arr.push("timestamp=" +parseInt(new Date().getTime() / ( * *)));
add_arr.sort();
var n_sign = add_arr.join('&');
var sign = hex_md5(encodeURIComponent(n_sign).toUpperCase());
var formData = new FormData();
formData.append('pic', document.querySelector('#pic').files[]);
formData.append('appcode', "PHRASE");
formData.append('name', "一叶孤舟");
formData.append('type', "background");
formData.append('font_color', "");
formData.append('price', "");
formData.append('state', "");
formData.append('description', "轻风无意助孤舟,任尔飘摇任尔游。");
formData.append('forever', "");
formData.append('sale_start', "");
formData.append('sale_end', "");
$.ajax({
url: "http://localhost:51650/api/AppletShop/AdminShop/AddSkin",
type: "post",
dataType: "json",
data: formData,
headers: { "sign": sign },
processData: false,
contentType: false,
success: function (data) {
if (data.success) {
alert(data.message);
}
},
error: function (data) {
alert(data);
}
});
});
});
</script>
}
好吧,先不吐槽我的加密字符串的加入方式。。。
如上,我们需要的是将参数加入到一个集合,然后排序,然后拼接成一个字符串,然后转码,然后MD5加密。里面的时间戳是表示这个sign是有时限的。
然后是拦截器的代码:
public override void OnActionExecuting(HttpActionContext actionContext)
{
//如果不需要检测直接返回
if (!isCheck)
return;
ApiResult resultMsg = new ApiResult();
List<string> list_params = new List<string>();
string action_name = actionContext.ActionDescriptor.ActionName;
list_params.Add("method=" + action_name);
//参数在queryparam上
var action_params = actionContext.ActionArguments;
foreach (var param in action_params)
{
list_params.Add(param.Key + "=" + param.Value);
}
var headers = actionContext.Request.Content.Headers; //如果是multipart/form-data请求
if (actionContext.Request.Content.IsMimeMultipartContent())
{
System.Collections.ObjectModel.Collection<HttpContent> formdata=new System.Collections.ObjectModel.Collection<HttpContent> ();
Task.Factory.StartNew(() => formdata = actionContext.Request.Content.ReadAsMultipartAsync().Result.Contents, CancellationToken.None, TaskCreationOptions.LongRunning, TaskScheduler.Default).Wait();
foreach (var form in formdata)
{
//文件不加入到加密字符串中
if (Util.isNotNull(form.Headers.ContentDisposition.FileName))
{
continue;
}
var key = form.Headers.ContentDisposition.Name.Replace("\"", "");
string val = form.ReadAsStringAsync().Result;
list_params.Add(key + "=" + val);
}
}
if (Util.isNotNull(headers.ContentType))
{
//各种请求类型(目前只支持下面三种和上面的formdata)
if (headers.ContentType.ToString() == "application/json")
{
var result = actionContext.Request.Content.ReadAsStringAsync().Result;
list_params.Add(result);
}
else if (headers.ContentType.ToString() == "text/plain; charset=UTF-8")
{
var result = actionContext.Request.Content.ReadAsStringAsync().Result;
list_params.Add(result);
}
else if (headers.ContentType.ToString() == "application/x-www-form-urlencoded")
{
var result = actionContext.Request.Content.ReadAsStringAsync().Result;
var _params = result.Split('&');
list_params.AddRange(_params);
}
} //加时间戳
long timespan_now = Util.GetTimestamp(DateTime.Now);
list_params.Add("timestamp=" + timespan_now / ( * *));
list_params.Sort(); //排序
//需要加密的字段
string sign_string = string.Join("&", list_params);
//从header中读取sign,timestamp.sign是方法名与方法参数的集合排序后通过&连接的字符串
string sign = SignToken.GetSignByHeader(actionContext.Request.Headers, "sign");
//string timestamp = SignToken.GetSignByHeader(actionContext.Request.Headers, "timestamp");
//判断请求头是否包含以下参数
if (string.IsNullOrEmpty(sign))
{
resultMsg = new ApiResult { success = false, status = Util.ApiStatusCode.InvalidParam, message = "请求头中缺少参数数据!" };
}
else
{
//服务端加密后的参数
string server_sign = Util.MD5Encrypt(HttpUtility.UrlEncode(sign_string).ToUpper()).ToLower();
if (server_sign != sign)
{
resultMsg = new ApiResult { success = false, status = Util.ApiStatusCode.Unauthorized, message = "签名或者密钥错误!" };
}
else
{
resultMsg.success = true;
} }
if (!resultMsg.success)
{
//如果验证不通过,则返回授权错误,并且写入错误原因
actionContext.Response = actionContext.Request.CreateResponse(resultMsg);
}
else
{ base.OnActionExecuting(actionContext);
}
}
我拦截器的处理方式是以获取参数为核心,不管你是什么请求方法(get,post,delete,put),只要你传了参数,然后我需要保证前后端的参数是一致的。这里就做了几个限制。
1.请求是Get是没问题,其他请求只支持 multipart/form-data,application/json,application/x-www-form-urlencoded,text/plain; charset=UTF-8,目前这些对我来说是够用了。然后每种方式传参方式咯有不同,前后端统一就可以了。
2.当有文件时,文件字段是不加入到加密字符中的
然后在调试过程中遇到过一个问题。在multipart/form-data情况下,actionContext.Request.Content.ReadAsMultipartAsync().Result.Contents会发生死锁,然后前端就一直等啊等,解决方法如上。
另外还有其他办法 https://stackoverflow.com/questions/15201255/request-content-readasmultipartasync-never-returns
webapi接口安全验证的更多相关文章
- ASP.NET MVC WebApi接口授权验证
对于很任何多开发者来说,不管是使用任何一种框架,或者是使用任何一种语言,都要使用面向接口编程.使用面向接口编程的时候,那么就会有很多的权限验证,用户验证等等. 特别是对于一些系统来说,别人想要对接你的 ...
- 使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证
使用ASP.NET Identity 实现WebAPI接口的Oauth身份验证 目前WEB 前后端分离的开发模式比较流行,之前做过的几个小项目也都是前后分离的模式,后端使用asp.net weba ...
- ASP.NET Core WebApi基于JWT实现接口授权验证
一.ASP.Net Core WebApi JWT课程前言 我们知道,http协议本身是一种无状态的协议,而这就意味着如果用户向我们的应用提供了用户名和密码来进行用户认证,那么下一次请求时,用户还要再 ...
- ASP.NET WEBAPI 的身份验证和授权
定义 身份验证(Authentication):确定用户是谁. 授权(Authorization):确定用户能做什么,不能做什么. 身份验证 WebApi 假定身份验证发生在宿主程序称中.对于 web ...
- 关于WEB Service&WCF&WebApi实现身份验证之WCF篇(2)
因前段时间工作变动(换了新工作)及工作较忙暂时中断了该系列文章,今天难得有点空闲时间,就继续总结WCF身份验证的其它方法.前面总结了三种方法(详见:关于WEB Service&WCF& ...
- WebApi接口访问异常问题。尝试创建“testController”类型的控制器时出错。请确保控制器具有无参数公共构造函数
本来运行的好好的webAPI 接口突然报了个 :“尝试创建“testController”类型的控制器时出错.请确保控制器具有无参数公共构造函数” 错误.耗了半宿最终解决了, 原因: api控制器中引 ...
- WebAPI接口安全校验
通过网上查看相关WebAPI接口验证的方法,整理了一下,直接上代码,功能不复杂,有问题留言, //--------------------------------------------------- ...
- WebApi接口安全性 接口权限调用、参数防篡改防止恶意调用
背景介绍 最近使用WebApi开发一套对外接口,主要是数据的外送以及结果回传,接口没什么难度,采用WebApi+EF的架构简单创建一个模板工程,使用template生成一套WebApi接口,去掉put ...
- 跟我一起学.NetCore之熟悉的接口权限验证不能少(Jwt)
前言 权限管控对于一个系统来说是非常重要的,最熟悉不过的是菜单权限和数据权限,上一节通过Jwt实现了认证,接下来用它实现接口权限的验证,为什么不是菜单权限呢?对于前后端分离而言,称其为接口权限感觉比较 ...
随机推荐
- 后台添加Textbox
/// <summary> /// behind add textbox /// </summary> private void AddTextToTextBox() { Te ...
- LeetCode刷题笔记(3)Java位运算符与使用按位异或(进制之间的转换)
1.问题描述 给定一个非空整数数组,除了某个元素只出现一次以外,其余每个元素均出现两次.找出那个只出现了一次的元素. 算法应该具有线性时间复杂度并且不使用额外空间. 输入: [4,1,2,1,2] 输 ...
- Redis(十二)flush误操作、Redis安全、处理bigkey和寻找热点key
一.flushall/flushdb误操作的处理 假设进行flush操作的Redis是一对主从结构的主节点,其中键值对的个数是100万,每秒写入量是1000. 1.缓存与存储 被误操作flush后,根 ...
- JAVA中的NIO (New IO)
简介 标准的IO是基于字节流和字符流进行操作的,而JAVA中的NIO是基于Channel和Buffer进行操作的. 传统IO graph TB; 字节流 --> InputStream; 字节流 ...
- python uiautomator,比 appium 更简单的 app 测试工具
1,场景 在 app 测试的蛮荒时代,如果要进行 app 自动化测试非常麻烦.张大胖如果想做安卓自动化测试,首先必须要学 Java.因为安卓自动化测试都绕不开 google 自己研发的自动化测试框架, ...
- 在虚拟机上的关于FTP FTP访问模式(匿名)
小知识 nfs和ftp类似另外一款共享软件 用21号端口 传控制 20号端口 传数据 Windows和虚拟机之间 接下来进行实验 首先在yum资源库中下载 输入命令:yum install vsft ...
- 【暂时停更】Gungame更新下载平台
v1.0: 这是本游戏的第一个版本, 制作于2019.4.12. 控制 : Player1: wsad为移动, r键开炮(有朝向限制) Player2: ikjl为移动, p键开炮(有朝向限制) 下载 ...
- [考试反思]1009csp-s模拟测试66:依旧
依旧是好一场烂一场. 依旧是那么菜. 依旧是难止颓废. 依旧是在此方仰望,幻想? 上面这段中二的东西是为了防止Parisb说我的标题与内容无关而diss我莫名其妙115的语文. 但是菜是的确是菜... ...
- Blue:贪心,单调队列
考场上什么都没想. 显然在扯淡了,应该说是刚开始想了一些没用的. 有决策单调性,所以二分答案? 好,那就二分答案.想想怎么检查每只蛤能不能都跳到终点? 那么每只蛤都不能掉队啊. 如果你现在遇到了一个石 ...
- Appium+python自动化(三十九)-Appium自动化测试框架综合实践 - 代码实现(超详解)
简介 经过一段时间的准备,完善的差不多了,继续分享有关Appium自动化测试框架综合实践.想必小伙伴们有点等不及了吧! driver配置封装 kyb_caps.yaml 配置表 参考代码 platfo ...