如何使用签名保证ASP.NET MVC OR WEBAPI的接口安全
更新时间:2021年04月28日 09:27:50 作者:Agile.Zhou
这篇文章主要介绍了如何使用签名保证ASP.NET MVC OR WEBAPI的接口安全,帮助大家更好的理解和学习使用.net技术,感兴趣的朋友可以了解下
目录签名算法
签名的参数
验证签名
ApiController基类
预防Replay Attack
客户端调用
当我们开发一款App的时候,App需要跟后台服务进行通信获取或者提交数据。如果我们没有完善的安全机制则很容易被别用心的人伪造请求而篡改数据。
所以我们需要使用某种安全机制来保证请求的合法。现在最常用的办法是给每个http请求添加一个签名,服务端来验证签名的合法性,如果签名合法则执行响应的操作,如果签名非法则直接拒绝请求。
签名算法
签名算法一般都使用Hash散列算法,常用的有MD5,SHA系列算法。这些算法可以根据不同的输入,计算出不同的结果,而且碰撞的概率很低。
签名算法跟加密算法不是一回事。很多同学都会说使用MD5加密一下,其实这是错误的。签名算法不能恢复原来的数据,因为它本身并不包含原来数据的信息。
而加密方法不同,加密方法是可以根据加密结果重新推算出原来的数据的。
HMAC SHA作为一种更加安全的签名算法,使用一个Key来影响签名的结果。这样同样的输入配合不同的Key可以得出不同的签名,更加安全。
public static string HmacSHA256(string secretKey,string plain)
{
var keyBytes = Encoding.UTF8.GetBytes(secretKey);
var plainBytes = Encoding.UTF8.GetBytes(plain);
using (var hmacsha256 = new HMACSHA256(keyBytes))
{
var sb = new StringBuilder();
var hashValue = hmacsha256.ComputeHash(plainBytes);
foreach (byte x in hashValue)
{
sb.Append(String.Format("{0:x2}", x));
}
return sb.ToString();
}
}
签名的参数
有了签名算法,那么我们签名的内容哪里来呢?
一般我们使用http请求的queryString然后加上时间戳还有随机数来作为签名的参数。
public static string MakeSignPlain(SortedDictionary<string,string> queryString,string time,string random )
{
var sb = new StringBuilder();
foreach (var keyValue in queryString)
{
sb.AppendFormat("{0}={1}&", keyValue.Key, keyValue.Value);
}
if (sb.Length>1)
{
sb.Remove(sb.Length - 1, 1);
}
sb.Append(time);
sb.Append(random);
return sb.ToString().ToUpper();
}
验证签名
验证签名就是简单的比较服务端生产的签名跟客户端生产的签名是否一直。
要注意的一点是最好验证下时间戳,跟服务端时间比较前后不能相差5分钟。这也是一个简单的防Replay Attack的手段。
public static bool Valid(string requestSign,string signPlain,string time, string secretKey)
{
if (string.IsNullOrEmpty(time)||string.IsNullOrEmpty(requestSign)||string.IsNullOrEmpty(signPlain))
{
return false;
}
//is in range
var now = DateTime.Now;
long requestTime =0;
if (long.TryParse(time,out requestTime))
{
var max = now.AddMinutes(5).ToString("yyyyMMddHHmmss");
var min = now.AddMinutes(-5).ToString("yyyyMMddHHmmss");
if (!(long.Parse(max) >= requestTime && long.Parse(min) <= requestTime))
{
return false;
}
}
else
{
return false;
}
//hashmac
var sign = Encryption.HmacSHA256(secretKey, signPlain);
return requestSign.Equals(sign, StringComparison.CurrentCultureIgnoreCase);
}
ApiController基类
有了上面这些铺垫我们就可以在基类完成签名的验证了。客户端需要把上面提到的时间戳,随机数,签名和客户端的ID放入http请求的headers里面。
我们在基类的OnActionExecuting里取出这些数据组合成签名的参数,然后根据客户端ID获取签名的Key,然后使用同样的签名算法计算签名。并且比较客户端的签名跟服务端的签名是否一致。
这里就不演示了。
预防Replay Attack
预防重放攻击主要有两点:
校验时间戳的范围
时间戳跟服务器时间相差在一个合理的范围内视为合法。
缓存签名
每次请求都去判断下签名是否出现过。如果出现过则视为非法请求。
因为有时间戳跟随机数的存在,所以理论上每次请求的签名是不可能重复的。
客户端调用
这里演示一下C#签名并且调用http接口的代码
[TestMethod()]
public void GetUserTest()
{
string url = "localhost:8090/api/test/GetUser";
string userId = "A39891D4-6CEF-4538-A562-3A422CA9C17A";
string appId = "100001";
string secretKey = "M/vkPOWXgBa7GnRd73t7j+jsKfbZtb+f";
string rumdon = Guid.NewGuid().ToString();
string time = DateTime.Now.ToString("yyyyMMddHHmmss");
//make signture plain text
var sortDict = new SortedDictionary<string, string>()
{
{"userId",userId }
};
var signPlain = new StringBuilder();
foreach (var keyValue in sortDict)
{
signPlain.AppendFormat("{0}={1}&", keyValue.Key, keyValue.Value);
}
if (signPlain.Length > 1)
{
//remove last &
signPlain.Remove(signPlain.Length - 1, 1);
}
signPlain.Append(time);
signPlain.Append(random);
Console.WriteLine("sign plain:{0}", signPlain.ToString().ToUpper());
//make sign
var sign = Encryption.HmacSHA256(secretKey, signPlain.ToString().ToUpper());
Console.WriteLine("sign:{0}", sign);
string requestUrl = string.Format("{0}?{1}={2}", url, "userId", userId);
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUrl);
request.Method = "GET";
//add headers
request.Headers.Add("time", time);
request.Headers.Add("appId", appId);
request.Headers.Add("random", random);
request.Headers.Add("sign", sign);
//
//start request
try
{
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
var responseStream = response.GetResponseStream();
if (responseStream != null)
{
using (StreamReader reader = new StreamReader(responseStream))
{
var content = reader.ReadToEnd();
Console.WriteLine(content);
}
}
}
}
catch (WebException ex)
{
using (HttpWebResponse response = (HttpWebResponse)ex.Response)
{
var responseStream = response.GetResponseStream();
if (responseStream != null)
{
using (StreamReader reader = new StreamReader(responseStream))
{
var content = reader.ReadToEnd();
Console.WriteLine(content);
}
}
}
}
}
以上就是如何使用签名保证ASP.NET MVC OR WEBAPI的接口安全的详细内容,更多关于用签名保证ASP.NET MVC OR WEBAPI的接口安全的资料请关注华域联盟其它相关文章!
您可能感兴趣的文章:asp.net mvc webapi 实用的接口加密方法示例ASP.NET Core MVC解决控制器同名Action请求不明确的问题如何在Asp.Net Core MVC中处理null值的实现创建一个ASP.NET MVC5项目的实现方法(图文)ASP.NET Core MVC如何实现运行时动态定义Controller类型asp.net mvc core管道及拦截器的理解ASP.NET Core MVC获取请求的参数方法示例ASP.NET Core MVC通过IViewLocationExpander扩展视图搜索路径的实现在ASP.NET Core Mvc集成MarkDown的方法ASP.NET Core MVC 中实现中英文切换的示例代码
ASP.NET
MVC
WEBAPI
接口
相关文章
解决DropDownList总是选中第一项的方法这篇文章主要介绍了解决DropDownList总是选中第一项的方法,DropDownList下拉框服务器控件是最常用的控件之一,虽然使用方便,但也会出现奇怪的错误,感兴趣的小伙伴们可以参考一下 2015-10-10
Asp.net ajax实现任务提示页面的简单代码这篇文章介绍了Asp.net ajax实现任务提示页面的简单代码,有需要的朋友可以参考一下 2013-11-11
ASP.NET加密解密算法分享这篇文章主要分享的是ASP.NET实现的加密解密算法,非常的简单使用,有需要的小伙伴快来参考下吧。 2015-03-03
Asp.net获取当前目录的方法小结有时候可能出现找不到类的情况,请引用System.Web.dll 2013-07-07
.net core如何利用ConcurrentTest组件对方法进行压力测试详解这篇文章主要给大家介绍了关于.net core如何利用ConcurrentTest组件对方法进行压力测试的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起看看吧 2018-11-11
ajaxToolkit:TextBoxWatermarkExtender演示与实现代码该控件的效果就是在TextBox控件上添加“水印”效果,也就是当TextBox为空时,显示提示消息,一旦TextBox聚焦,样式就消失,看起来还挺不错的吗,感兴趣的你可以了解下哦,希望本文对你有所帮助 2013-01-01
asp.net 中静态方法和动态方法调用的区别实例分析动态方法,在使用时需要先创建实例,才能调用实例方法,而静态方法则不需要,直接使用即可。 2013-06-06
asp.net updatepanel 导致JS不能加载,而无法使用的解决方法asp.net updatepanel 局部刷新,导致JS不能加载,而无法使用,而且 updatepanel会刷两次,郁闷的,解决方法如下 2013-08-08
DataGrid同时具有分页和排序功能及注意点DataGrid同时具有分页和排序功能及注意点... 2006-09-09
WPF图形解锁控件ScreenUnLock使用详解这篇文章主要为大家详细介绍了WPF图形解锁控件ScreenUnLock的使用方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下 2017-07-07
最新评论
本文由 华域联盟 原创撰写:华域联盟 » 如何使用签名保证ASP.NET MVC OR WEBAPI的接口安全
转载请保留出处和原文链接:https://www.cnhackhy.com/4922.htm