精品熟女碰碰人人a久久,多姿,欧美欧美a v日韩中文字幕,日本福利片秋霞国产午夜,欧美成人禁片在线观看

如何使用簽名保證ASP.NET MVC OR WEBAPI的接口安全

如何使用簽名保證asp.net mvc or webapi的接口安全

當(dāng)我們開(kāi)發(fā)一款app的時(shí)候,app需要跟后臺(tái)服務(wù)進(jìn)行通信獲取或者提交數(shù)據(jù)。如果我們沒(méi)有完善的安全機(jī)制則很容易被別用心的人偽造請(qǐng)求而篡改數(shù)據(jù)。
所以我們需要使用某種安全機(jī)制來(lái)保證請(qǐng)求的合法。現(xiàn)在最常用的辦法是給每個(gè)http請(qǐng)求添加一個(gè)簽名,服務(wù)端來(lái)驗(yàn)證簽名的合法性,如果簽名合法則執(zhí)行響應(yīng)的操作,如果簽名非法則直接拒絕請(qǐng)求。

 

簽名算法

簽名算法一般都使用hash散列算法,常用的有md5,sha系列算法。這些算法可以根據(jù)不同的輸入,計(jì)算出不同的結(jié)果,而且碰撞的概率很低。
簽名算法跟加密算法不是一回事。很多同學(xué)都會(huì)說(shuō)使用md5加密一下,其實(shí)這是錯(cuò)誤的。簽名算法不能恢復(fù)原來(lái)的數(shù)據(jù),因?yàn)樗旧聿⒉话瓉?lái)數(shù)據(jù)的信息。
而加密方法不同,加密方法是可以根據(jù)加密結(jié)果重新推算出原來(lái)的數(shù)據(jù)的。
hmac sha作為一種更加安全的簽名算法,使用一個(gè)key來(lái)影響簽名的結(jié)果。這樣同樣的輸入配合不同的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();
          }
      }

 

簽名的參數(shù)

有了簽名算法,那么我們簽名的內(nèi)容哪里來(lái)呢?
一般我們使用http請(qǐng)求的querystring然后加上時(shí)間戳還有隨機(jī)數(shù)來(lái)作為簽名的參數(shù)。

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();
      }

 

驗(yàn)證簽名

驗(yàn)證簽名就是簡(jiǎn)單的比較服務(wù)端生產(chǎn)的簽名跟客戶端生產(chǎn)的簽名是否一直。
要注意的一點(diǎn)是最好驗(yàn)證下時(shí)間戳,跟服務(wù)端時(shí)間比較前后不能相差5分鐘。這也是一個(gè)簡(jiǎn)單的防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基類

有了上面這些鋪墊我們就可以在基類完成簽名的驗(yàn)證了。客戶端需要把上面提到的時(shí)間戳,隨機(jī)數(shù),簽名和客戶端的id放入http請(qǐng)求的headers里面。
我們?cè)诨惖膐nactionexecuting里取出這些數(shù)據(jù)組合成簽名的參數(shù),然后根據(jù)客戶端id獲取簽名的key,然后使用同樣的簽名算法計(jì)算簽名。并且比較客戶端的簽名跟服務(wù)端的簽名是否一致。
這里就不演示了。

 

預(yù)防replay attack

預(yù)防重放攻擊主要有兩點(diǎn):

  • 校驗(yàn)時(shí)間戳的范圍

時(shí)間戳跟服務(wù)器時(shí)間相差在一個(gè)合理的范圍內(nèi)視為合法。

  • 緩存簽名

每次請(qǐng)求都去判斷下簽名是否出現(xiàn)過(guò)。如果出現(xiàn)過(guò)則視為非法請(qǐng)求。
因?yàn)橛袝r(shí)間戳跟隨機(jī)數(shù)的存在,所以理論上每次請(qǐng)求的簽名是不可能重復(fù)的。

 

客戶端調(diào)用

這里演示一下c#簽名并且調(diào)用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<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的接口安全的詳細(xì)內(nèi)容,更多關(guān)于用簽名保證asp.net mvc or webapi的接口安全的資料請(qǐng)關(guān)注碩編程其它相關(guān)文章!

下一節(jié):asp.net core 集成 react spa應(yīng)用的步驟

asp.net編程技術(shù)

相關(guān)文章