• C# 通用 HTTP 签名组件的另类实现


    1、初衷

    开发中经常需要做一些接口的签名生成和校验工作,最开始的时候都是每个接口去按照约定单独实现,久而久之就变的非常难维护,因此就琢磨怎么能够写了一个比较通用的签名生成工具。

    2、思路

    采用链式调用的方式,使得签名的步骤可以动态拼凑组合。

    3、直接看效果

    //设置数据源
    var signSource = new Dictionary<string, string>()
    {
    { "param1", "1" },
    { "param3", "3+" },
    { "param2", "2" }
    };
    var signer = new HttpSigner();
    signer.SetSignData(signSource);
    //设置数据源并配置规则
    signer.SetSignData(signSource, setting =>
    {
    //按参数名排序
    //result --> param1 param2 param3
    setting.IsOrderByWithKey = false;
    //是否对签名数据的参数值进行UrlEncode
    setting.IsDoUrlEncodeForSourceValue = false;
    //签名主体是否包含参数名
    setting.IsSignTextContainKey = true;
    //签名主体中参数和参数值的连接符(需要启用IsSignTextContainKey)
    setting.SignTextKeyValueSeparator = "=";
    //签名主体中不同参数项的连接符
    setting.SignTextItemSeparator = "&";
    //以上都开启后 --> param1=1¶m2=2¶m3=3
    //编码
    setting.DefaultEncoding = Encoding.UTF8;
    });
    //签名主体设置前缀
    signer.SetSignData(signSource).SetSignTextPrefix("TestPrefix");
    //签名主体设置后缀
    signer.SetSignData(signSource).SetSignTextSuffix("TestSuffix");
    //签名主体进行Base64
    signer.SetSignData(signSource).SetSignTextBase64();
    //签名主体进行MD5,(方法参数为签名结果是否转小写)
    signer.SetSignData(signSource).SetSignTextMD5(bool isToLower = true);
    //签名主体进行SHA1,(方法参数为签名结果是否转小写)
    signer.SetSignData(signSource).SetSignTextSHA1(bool isToLower = true);
    //获取签名结果
    string signString = signer.SetSignData(signSource).GetSignResult();
    //组合调用
    string signString = signer.SetSignData(signSource).SetSignTextBase64().SetSignTextMD5().SetSignTextSHA1();

    4、代码实现

    HttpSignItem类

    用于保存签名的参数集合。

    namespace JiuLing.CommonLibs.Security.HttpSign
    {
    internal class HttpSignItem
    {
    public string Key { get; set; }
    public string Value { get; set; }
    public HttpSignItem(string key, string value)
    {
    Key = key;
    Value = value;
    }
    }
    }

    HttpSignSetting类

    用于签名的基本配置。

    using System.Text;
    namespace JiuLing.CommonLibs.Security.HttpSign
    {
    ///
    /// 签名配置
    ///
    public class HttpSignSetting
    {
    ///
    /// 是否按参数名进行排序
    ///
    public bool IsOrderByWithKey { get; set; } = false;
    ///
    /// 是否对签名数据的参数值进行UrlEncode
    ///
    public bool IsDoUrlEncodeForSourceValue { get; set; } = false;
    ///
    /// 签名主体是否包含参数名
    ///
    public bool IsSignTextContainKey { get; set; } = true;
    ///
    /// 签名主体中参数和参数值的连接符(需要启用IsSignTextContainKey)
    ///
    public string SignTextKeyValueSeparator { get; set; } = "=";
    ///
    /// 签名主体中不同参数项的连接符
    ///
    public string SignTextItemSeparator { get; set; } = "&";
    ///
    /// 编码
    ///
    public Encoding DefaultEncoding { get; set; } = Encoding.UTF8;
    }
    }

    HttpSigner类

    签名组件的具体实现。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    namespace JiuLing.CommonLibs.Security.HttpSign
    {
    ///
    /// 网络请求签名工具
    ///
    public class HttpSigner
    {
    ///
    /// 签名配置
    ///
    private readonly HttpSignSetting _setting = new HttpSignSetting();
    ///
    /// 最终的签名串
    ///
    private string _signString;
    ///
    /// 设置签名数据
    ///
    /// 待签名的键值对
    /// 配置签名规则
    ///
    ///
    public HttpSigner SetSignData(Dictionary<string, string> signSource, Action setting = null)
    {
    setting?.Invoke(_setting);
    if (_setting == null)
    {
    throw new ArgumentNullException("无效的签名配置", "setting");
    }
    if (signSource == null || signSource.Count == 0)
    {
    throw new ArgumentException("待签名数据异常", nameof(signSource));
    }
    var signSourceList = new List(signSource.Count);
    foreach (var item in signSource)
    {
    var itemValue = item.Value;
    if (_setting.IsDoUrlEncodeForSourceValue)
    {
    itemValue = System.Web.HttpUtility.UrlEncode(itemValue, _setting.DefaultEncoding);
    }
    signSourceList.Add(new HttpSignItem(item.Key, itemValue));
    }
    if (_setting.IsOrderByWithKey)
    {
    signSourceList = signSourceList.OrderBy(x => x.Key).ToList();
    }
    if (_setting.IsSignTextContainKey)
    {
    _signString = string.Join(_setting.SignTextItemSeparator, signSourceList.Select(x => $"{x.Key}{_setting.SignTextKeyValueSeparator}{x.Value}"));
    }
    else
    {
    _signString = string.Join(_setting.SignTextItemSeparator, signSourceList.Select(x => x.Value));
    }
    return this;
    }
    ///
    /// 签名主体设置前缀
    ///
    /// 前缀值
    ///
    public HttpSigner SetSignTextPrefix(string input)
    {
    _signString = $"{input}{_signString}";
    return this;
    }
    ///
    /// 签名主体设置后缀
    ///
    /// 后缀值
    ///
    public HttpSigner SetSignTextSuffix(string input)
    {
    _signString = $"{_signString}{input}";
    return this;
    }
    ///
    /// 签名主体设置后缀
    ///
    ///
    public HttpSigner SetUrlEncode()
    {
    _signString = System.Web.HttpUtility.UrlEncode(_signString, _setting.DefaultEncoding);
    return this;
    }
    ///
    /// 签名主体进行Base64
    ///
    ///
    public HttpSigner SetSignTextBase64()
    {
    _signString = Base64Utils.GetStringValue(_signString);
    return this;
    }
    ///
    /// 签名主体进行MD5
    ///
    /// 签名结果是否转小写
    ///
    public HttpSigner SetSignTextMD5(bool isToLower = true)
    {
    if (isToLower)
    {
    _signString = MD5Utils.GetStringValueToLower(_signString);
    }
    else
    {
    _signString = MD5Utils.GetStringValueToUpper(_signString);
    }
    return this;
    }
    ///
    /// 签名主体进行SHA1
    ///
    /// 签名结果是否转小写
    ///
    public HttpSigner SetSignTextSHA1(bool isToLower = true)
    {
    if (isToLower)
    {
    _signString = SHA1Utils.GetStringValueToLower(_signString);
    }
    else
    {
    _signString = SHA1Utils.GetStringValueToUpper(_signString);
    }
    return this;
    }
    ///
    /// 获取签名结果
    ///
    ///
    public string GetSignResult()
    {
    return _signString;
    }
    }
    }

    5、附上仓库地址

    以上代码包含在我的通用类库中,可以直接Nuget搜索JiuLing.CommonLibs安装。
    GitHub类库地址
    文章代码地址

  • 相关阅读:
    【C基础篇】之数据类型
    基于PHP+mysql的车辆保险理赔系统
    尚硅谷Docker核心技术
    基于SpringBoot的墙绘产品展示交易平台设计与实现
    Tomcat打包部署spring boot项目
    SQL完整性约束
    安装zabbix-agent监控linux
    第十八章 类和对象——多态
    HelloWorld:通过demo,构建黑盒模型
    echarts鼠标滑动缩放后会自动回弹(已解决)
  • 原文地址:https://www.cnblogs.com/JiuLing-zhang/p/16732526.html