编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

Asp.netCore3.0 简单的webapi接口 (下)

wxchong 2024-06-24 19:42:30 开源技术 23 ℃ 0 评论

增加接口参数签名验证

接口签名算法

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

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

特别注意以下重要规则:

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

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

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

比如说:
第一步:对参数按照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;
        }
    }
}

下面是增加接口异常处理

增加接口异常处理

增加异常处理类

在项目下新增一个类,ExceptionFilter.cs 然后继承IExceptionFilter。当接口出现异常时我们统一返回一段json字符串{ "code": 0, "message": "异常提示" },剩下的代码如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;

namespace XXX.api
{
    /// <summary>
    /// 自定义webapi异常处理
    /// </summary>
    public class MyExceptionFilter : IExceptionFilter
    {
        /// <summary>
        /// 发送异常时执行的代码
        /// </summary>
        /// <param name="context"></param>
        public void OnException(ExceptionContext context)
        {
            Models.RetModel ret = new Models.RetModel();
            ret.code = 0;
            ret.message = "异常提示";
            string errRet= Newtonsoft.Json.JsonConvert.SerializeObject(ret);
            if (context.ExceptionHandled==false)
            {
                context.Result = new ContentResult
                {
                    Content = errRet,
                    StatusCode = StatusCodes.Status200OK,
                    ContentType="application/json"
                };
            }
            context.ExceptionHandled = true;
        }
        /// <summary>
        /// 异步发送异常时执行的代码
        /// </summary>
        /// <param name="context"></param>
        /// <returns></returns>
        public Task OnExceptionAsync(ExceptionContext context)
        {
            OnException(context);
            return Task.CompletedTask;
        }
    }
}

配置Startup.cs

在ConfigureServices中添加过滤器,MyExceptionFilter就是上面我们自定义的异常过滤器

 services.AddControllers(option=> {
                option.Filters.Add(new MyExceptionFilter());
            });

最后我们可以使用postman或者Swagger接口文档来测试一下。

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表