温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

ASP.NET MVC OR WebAPI的接口安全怎么实现

发布时间:2021-12-06 15:15:15 来源:亿速云 阅读:188 作者:iii 栏目:编程语言

这篇文章主要讲解了“ASP.NET MVC OR WebAPI的接口安全怎么实现”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“ASP.NET MVC OR WebAPI的接口安全怎么实现”吧!

  当我们开发一款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 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 = "http://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()

  {

  {"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的接口安全怎么实现这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI