通過前幾個(gè)教程的學(xué)習(xí)袄膏,對webapi的編寫基本上就可以入門了,可以做項(xiàng)目了甫煞,今天我們再給接口加個(gè)參數(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ū)分大小寫;
◆ 驗(yàn)證調(diào)用返回或主動(dòng)通知簽名時(shí)诸衔,傳送的sign參數(shù)不參與簽名盯漂,將生成的簽名與該sign值作校驗(yàn)。
第二步署隘,在stringA最后拼接上key得到stringSignTemp字符串宠能,并對stringSignTemp進(jìn)行MD5運(yùn)算,再將得到的字符串所有字符轉(zhuǎn)換為大寫磁餐,得到sign值signValue违崇。
◆ key設(shè)置:將key設(shè)置在接口配置文件中,當(dāng)key發(fā)生泄露時(shí)可第一時(shí)間通過修改配置文件來更改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>
/// 驗(yàn)證用戶請求參數(shù)
/// </summary>
/// <param name="p">參數(shù)中需要包含sign字段伴箩,用來驗(yàn)證簽名是否正確</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())
{
//簽名驗(yàn)證成功
return true;
}
else
{
//簽名失敗
return false;
}
}
catch (Exception ex)
{
//簽名異常信息
return false;
}
}
}
}
第三步鄙漏,驗(yàn)證
using System.Linq;
namespace XXX.Bo
{
public class UserBo
{
public static XXXContext db = new XXXContext();
/// <summary>
/// 增加一個(gè)用戶數(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))//驗(yàn)證用戶參數(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;
}
}
}
完
項(xiàng)目已經(jīng)上傳github嗤谚,看自行下載。
NetCore3.0-WebApi
求贊
創(chuàng)作不易怔蚌,喜歡的請給個(gè)免費(fèi)的贊吧巩步!