.Netcore.NETASP.NET Core见识录

Asp.netCore3.0 WebApi从0到1手摸手教你写【

2019-10-24  本文已影响0人  我是Mr小赵先生

通过前几个教程的学习,对webapi的编写基本上就可以入门了,可以做项目了,今天我们再给接口加个参数签名认证,之前的接口相当于赤果果的暴露在了网络上,只要知道接口地址、接口调用方式和传参就可以畅所欲为的调用接口了,这给我们写的webapi带来了很大的安全隐患,所以这篇教程是给webapi加上一层保护措施,可能算不上最优解决方案,但起码能起到一定的保护措施。

保护思路

1.接口调用采用POST的方式,可以屏蔽一部分小白,增加接口调用的难度。
2.接口调用参数增加签名字段,一可以防止数据被篡改,二还可以防止其它人非法调用我们的接口。

接口签名算法

签名生成的通用步骤如下:

第一步,设所有发送或者接收到的数据为集合M,将集合M内非空参数值的参数按照参数名ASCII码从小到大排序(字典序),使用URL键值对的格式(即key1=value1&key2=value2…)拼接成字符串stringA。

特别注意以下重要规则:

◆ 参数名ASCII码从小到大排序(字典序);
◆ 如果参数的值为空不参与签名;
◆ 参数名区分大小写;
◆ 验证调用返回或主动通知签名时,传送的sign参数不参与签名,将生成的签名与该sign值作校验。

第二步,在stringA最后拼接上key得到stringSignTemp字符串,并对stringSignTemp进行MD5运算,再将得到的字符串所有字符转换为大写,得到sign值signValue。

◆ key设置:将key设置在接口配置文件中,当key发生泄露时可第一时间通过修改配置文件来更改key值。

举例:

假设传送的参数如下:

a:  aa
b:  bb
c:  cc

第一步:对参数按照key=value的格式,并按照参数名ASCII字典序排序如下:
stringA="a=aa&b=bb&c=cc";

第二步:拼接API密钥:
stringSignTemp=stringA+"&key=afwfsfwexwegw" //注:key为用户在配置文件中自行设置的
sign=MD5(stringSignTemp).toUpperCase()="9A0A8659F005D6984697E2CA0A9CF3B7" //注:MD5签名方式

代码部分

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

    
{
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  //接口配置参数设置
  "AppSettings": {
    //数据库连接字符串
    "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>
        /// 验证用户请求参数
        /// </summary>
        /// <param name="p">参数中需要包含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)//如果参数不为空则拼接参数
                    {
                        value = oValue.ToString();
                        //判断参数是否为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>
        /// 增加一个用户数据
        /// </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))//验证用户参数签名是否合法
            {
                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 = "数据插入成功";
                    }
                    else
                    {
                        r.code = 0;
                        r.message = "数据插入成功";
                    }
                }
                else
                {
                    r.code = 0;
                    r.message = "手机号已经存在";
                }
            }
            else
            {
                r.code = 0;
                r.message = "签名失败";
            }
            return r;
        }
    }
}

项目已经上传github,看自行下载。
NetCore3.0-WebApi

求赞

创作不易,喜欢的请给个免费的赞吧!

上一篇 下一篇

猜你喜欢

热点阅读