Asp.netCore3.0 WebApi從0到1手摸手教你寫【5】增加接口參數(shù)簽名驗證

通過前幾個教程的學(xué)習(xí),對webapi的編寫基本上就可以入門了,可以做項目了,今天我們再給接口加個參數(shù)簽名認(rèn)證,之前的接口相當(dāng)于赤果果的暴露在了網(wǎng)絡(luò)上,只要知道接口地址、接口調(diào)用方式和傳參就可以暢所欲為的調(diào)用接口了,這給我們寫的webapi帶來了很大的安全隱患,所以這篇教程是給webapi加上一層保護(hù)措施,可能算不上最優(yōu)解決方案,但起碼能起到一定的保護(hù)措施。

保護(hù)思路

1.接口調(diào)用采用POST的方式,可以屏蔽一部分小白,增加接口調(diào)用的難度。
2.接口調(diào)用參數(shù)增加簽名字段,一可以防止數(shù)據(jù)被篡改,二還可以防止其它人非法調(diào)用我們的接口。

接口簽名算法

簽名生成的通用步驟如下:

第一步,設(shè)所有發(fā)送或者接收到的數(shù)據(jù)為集合M,將集合M內(nèi)非空參數(shù)值的參數(shù)按照參數(shù)名ASCII碼從小到大排序(字典序),使用URL鍵值對的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特別注意以下重要規(guī)則:

◆ 參數(shù)名ASCII碼從小到大排序(字典序);
◆ 如果參數(shù)的值為空不參與簽名;
◆ 參數(shù)名區(qū)分大小寫;
◆ 驗證調(diào)用返回或主動通知簽名時,傳送的sign參數(shù)不參與簽名,將生成的簽名與該sign值作校驗。

第二步,在stringA最后拼接上key得到stringSignTemp字符串,并對stringSignTemp進(jìn)行MD5運(yùn)算,再將得到的字符串所有字符轉(zhuǎn)換為大寫,得到sign值signValue。

◆ key設(shè)置:將key設(shè)置在接口配置文件中,當(dāng)key發(fā)生泄露時可第一時間通過修改配置文件來更改key值。

舉例:

假設(shè)傳送的參數(shù)如下:

a:  aa
b:  bb
c:  cc

第一步:對參數(shù)按照key=value的格式,并按照參數(shù)名ASCII字典序排序如下:
stringA="a=aa&b=bb&c=cc";

第二步:拼接API密鑰:
stringSignTemp=stringA+"&key=afwfsfwexwegw" //注:key為用戶在配置文件中自行設(shè)置的
sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7" //注:MD5簽名方式

代碼部分

第一步,在配置文件增加簽名的key
appsettings.json

    
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  //接口配置參數(shù)設(shè)置
  "AppSettings": {
    //數(shù)據(jù)庫連接字符串
    "xxxDB": "Server=ROBERT-PC\\SQLEXPRESS;User Id=xiaozhao;Password=xz123789;Database=XXX;",
    //接口是否需要簽名
    "IsSign": "false",
    //16位MD5簽名key
    "Md5Key": "5ShiCeShiAAAAAAA"
  }

}

第二步,在Common增加SignMgr.cs類

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using XXX.Models;

namespace XXX.Common
{
    /// <summary>
    /// 簽名管理
    /// </summary>
    public class SignMgr
    {
        /// <summary>
        /// 驗證用戶請求參數(shù)
        /// </summary>
        /// <param name="p">參數(shù)中需要包含sign字段,用來驗證簽名是否正確</param>
        /// <returns></returns>
        public static bool ParamVerify(Object p)
        {
            //獲取是否簽名字段
            string isSign = AppSettings.GetAppSeting("IsSign");
            //獲取MD5簽名字段
            string secretKey = AppSettings.GetAppSeting("Md5Key");
            if (isSign == "false")
            {
                return true;
            }
            try
            {
                Type t = p.GetType();
                var propertys = t.GetProperties();
                string sign = "";
                string temp = "";
                var orderPropertys = propertys.OrderBy(p => p.Name); //ASCII碼從小到大排序(字典序)
                foreach (var item in orderPropertys)
                {
                    string name = item.Name;
                    object oValue = item.GetValue(p);
                    string value = "";
                    if (oValue != null)//如果參數(shù)不為空則拼接參數(shù)
                    {
                        value = oValue.ToString();
                        //判斷參數(shù)是否為sign,sign不參與簽名
                        if (name != "sign")
                        {
                            temp += name + "=" + value + "&";
                        }
                        else
                        {
                            sign = value;
                        }
                    }
                }

                temp +="key=" +secretKey;
                string md = Md5Encrypt.MD5(temp);
                if (sign != "" && sign.ToUpper() == md.ToUpper())
                {
                    //簽名驗證成功
                    return true;
                }
                else
                {
                    //簽名失敗
                    return false;
                }
            }
            catch (Exception ex)
            {
                //簽名異常信息
                return false;
            }
        }

        
    }
}

第三步,驗證

using System.Linq;

namespace XXX.Bo
{
    public class UserBo
    {
        public static XXXContext db = new XXXContext();
        /// <summary>
        /// 增加一個用戶數(shù)據(jù)
        /// </summary>
        /// <param name="model"></param>
        public static Models.User.AddUserR AddUser(Models.User.AddUserP model)
        {
            var r = new Models.User.AddUserR();
            if (Common.SignMgr.ParamVerify(model))//驗證用戶參數(shù)簽名是否合法
            {
                Models.XXXEntities.User userSearch = (from u in db.User where u.Phone == model.phone select u).FirstOrDefault();
                if (userSearch == null)
                {
                    Models.XXXEntities.User user = new Models.XXXEntities.User();
                    user.Phone = model.phone;
                    user.Password = model.password;
                    user.NickName = model.nickName;
                    user.State = model.state;
                    db.User.Add(user);
                    int i = db.SaveChanges();
                    if (i > 0)
                    {
                        r.code = 1;
                        r.message = "數(shù)據(jù)插入成功";
                    }
                    else
                    {
                        r.code = 0;
                        r.message = "數(shù)據(jù)插入成功";
                    }
                }
                else
                {
                    r.code = 0;
                    r.message = "手機(jī)號已經(jīng)存在";
                }
            }
            else
            {
                r.code = 0;
                r.message = "簽名失敗";
            }
            return r;
        }
    }
}

項目已經(jīng)上傳github,看自行下載。
NetCore3.0-WebApi

求贊

創(chuàng)作不易,喜歡的請給個免費(fèi)的贊吧!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容