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&param2=2&param3=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
{
/// <summary>
/// 签名配置
/// </summary>
public class HttpSignSetting
{
/// <summary>
/// 是否按参数名进行排序
/// </summary>
public bool IsOrderByWithKey { get; set; } = false; /// <summary>
/// 是否对签名数据的参数值进行UrlEncode
/// </summary>
public bool IsDoUrlEncodeForSourceValue { get; set; } = false; /// <summary>
/// 签名主体是否包含参数名
/// </summary>
public bool IsSignTextContainKey { get; set; } = true; /// <summary>
/// 签名主体中参数和参数值的连接符(需要启用IsSignTextContainKey)
/// </summary>
public string SignTextKeyValueSeparator { get; set; } = "="; /// <summary>
/// 签名主体中不同参数项的连接符
/// </summary>
public string SignTextItemSeparator { get; set; } = "&"; /// <summary>
/// 编码
/// </summary>
public Encoding DefaultEncoding { get; set; } = Encoding.UTF8;
}
}

HttpSigner类

签名组件的具体实现。

using System;
using System.Collections.Generic;
using System.Linq; namespace JiuLing.CommonLibs.Security.HttpSign
{
/// <summary>
/// 网络请求签名工具
/// </summary>
public class HttpSigner
{
/// <summary>
/// 签名配置
/// </summary>
private readonly HttpSignSetting _setting = new HttpSignSetting();
/// <summary>
/// 最终的签名串
/// </summary>
private string _signString; /// <summary>
/// 设置签名数据
/// </summary>
/// <param name="signSource">待签名的键值对</param>
/// <param name="setting">配置签名规则</param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public HttpSigner SetSignData(Dictionary<string, string> signSource, Action<HttpSignSetting> 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<HttpSignItem>(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;
} /// <summary>
/// 签名主体设置前缀
/// </summary>
/// <param name="input">前缀值</param>
/// <returns></returns>
public HttpSigner SetSignTextPrefix(string input)
{
_signString = $"{input}{_signString}";
return this;
} /// <summary>
/// 签名主体设置后缀
/// </summary>
/// <param name="input">后缀值</param>
/// <returns></returns>
public HttpSigner SetSignTextSuffix(string input)
{
_signString = $"{_signString}{input}";
return this;
} /// <summary>
/// 签名主体设置后缀
/// </summary>
/// <returns></returns>
public HttpSigner SetUrlEncode()
{
_signString = System.Web.HttpUtility.UrlEncode(_signString, _setting.DefaultEncoding);
return this;
} /// <summary>
/// 签名主体进行Base64
/// </summary>
/// <returns></returns>
public HttpSigner SetSignTextBase64()
{
_signString = Base64Utils.GetStringValue(_signString);
return this;
} /// <summary>
/// 签名主体进行MD5
/// </summary>
/// <param name="isToLower">签名结果是否转小写</param>
/// <returns></returns>
public HttpSigner SetSignTextMD5(bool isToLower = true)
{
if (isToLower)
{
_signString = MD5Utils.GetStringValueToLower(_signString);
}
else
{
_signString = MD5Utils.GetStringValueToUpper(_signString);
}
return this;
} /// <summary>
/// 签名主体进行SHA1
/// </summary>
/// <param name="isToLower">签名结果是否转小写</param>
/// <returns></returns>
public HttpSigner SetSignTextSHA1(bool isToLower = true)
{
if (isToLower)
{
_signString = SHA1Utils.GetStringValueToLower(_signString);
}
else
{
_signString = SHA1Utils.GetStringValueToUpper(_signString);
}
return this;
} /// <summary>
/// 获取签名结果
/// </summary>
/// <returns></returns>
public string GetSignResult()
{
return _signString;
}
}
}

5、附上仓库地址

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

GitHub类库地址

文章代码地址

通用 HTTP 签名组件的另类实现的更多相关文章

  1. ASP.NET通用权限验证组件实现

    沙发(SF)通用权限验证组件 开篇 本篇介绍通用权限验证的实现代码思路,总共分为导入参数.解析XML.根据XML配置进行处理.返回结果. 代码架构图 1.   类介绍 1.SFWebPermissio ...

  2. SNFAutoupdater通用自动升级组件V2.0

    1.组件介绍 C/S构的特点是能充分发挥客户端的处理能力,很多工作可以由客户端处理后再提交给服务器,对应的优点就是客户端响应速度快模式客户端以其强大的功能,丰富的表现力受到相当大部分用户的青睐,但是客 ...

  3. 如何通过 Vue+Webpack 来做通用的前端组件化架构设计

    目录:   1. 架构选型     2. 架构目录介绍     3. 架构说明     4. 招聘消息 目前如果要说比较流行的前端架构哪家强,屈指可数:reactjs.angularjs.emberj ...

  4. 给 Web 开发人员推荐的通用独立 UI 组件(二)

    现代 Web 开发在将体验和功能做到极致的同时,对于美观的追求也越来越高.在推荐完图形库之后,再来推荐一些精品的独立 UI 组件.这些组件可组合在一起,形成美观而交互强大的 Web UI . 给 We ...

  5. Blazor组件自做二 : 使用JS隔离制作手写签名组件

    Blazor组件自做二 : 使用JS隔离制作手写签名组件 本文相关参考链接 JavaScript 模块中的 JavaScript 隔离 Viewer.js工程 Blazor组件自做一 : 使用JS隔离 ...

  6. Blazor组件自做四 : 使用JS隔离封装signature_pad签名组件

    运行截图 演示地址 响应式演示 感谢szimek写的棒棒的signature_pad.js项目, 来源: https://github.com/szimek/signature_pad 正式开始 1. ...

  7. 《Nodejs开发加密货币》之二十七:开发通用的HTML组件

    人的懒惰常常是麻烦的开始.多数程序员都希望自己的工作一劳永逸,一次开发,到处使用,成了人人追逐的目标,我也不例外.最初写<Nodejs开发加密货币>系列文章,因为不喜欢设定好了去写,所以目 ...

  8. Tsx写一个通用的button组件

    一年又要到年底了,vue3.0都已经出来了,我们也不能一直还停留在过去的js中,是时候学习并且在项目中使用一下Ts了. 如果说jsx是基于js的话,那么tsx就是基于typescript的 废话也不多 ...

  9. 容器扩展属性 IExtenderProvider 实现WinForm通用数据验证组件

    大家对如下的Tip组件使用应该不陌生,要想让窗体上的控件使用ToolTip功能,只需要拖动一个ToolTip组件到窗口,所有的控件就可以使用该功能,做信息提示. 本博文要记录的,就是通过容器扩展属性 ...

随机推荐

  1. c++小游戏--五子棋

    大家好,我是芝麻狐! 这是我自制的小游戏,目前仅支持devc++. 如果你没有c++软件, 请打开网站GDB online Debugger | Compiler - Code, Compile, R ...

  2. sql语句实现每日资格设置

    CREATE TABLE 'iDayAuth'( 'openid' VARCHAR(16) NOT NULL , 'iStamp' INT(10) NOT NULL, 'iDayAuth' SMALL ...

  3. 精心总结十三条建议,帮你创建更合适的MySQL索引

    上篇文章讲到使用MySQL的Explain命令可以分析SQL性能瓶颈,优化SQL查询,以及查看是否用到了索引. 我们都知道创建索引可以提高查询效率,但是具体该怎么创建索引? 哪些字段适合创建索引? 哪 ...

  4. 在Mac Os(苹果)上用手机抓包软件Charles抓取微信小程序中的高清无水印视频

    原文转载自「刘悦的技术博客」https://v3u.cn/a_id_118 手机抓包是一名测试工程师常备的技能,比如我想查看一个接口请求的参数.返回值,还有移动设备上的http请求.https请求,这 ...

  5. 一个注解搞定SpringBoot接口定制属性加解密

    前言 上个月公司另一个团队做的新项目上线后大体上运行稳定,但包括研发负责人在内的两个人在项目上线后立马就跳槽了,然后又交接给了我这个「垃圾回收人员」. 本周甲方另一个厂家的监控平台扫描到我们这个项目某 ...

  6. JavaScript 函数对象(Function 对象)

    函数对象 当我们对函数使用 typeof 操作符会返回什么? function f() { console.log('hello') } console.dir(typeof f) // functi ...

  7. 如何在 HTML 中调整图像大小?

    了解在 HTML 中调整图像大小的不同技术.何时应避免在浏览器端调整大小,以及在 Web 上操作和提供图像的正确方法. 如果您的图像不适合布局,您可以在 HTML 中调整其大小.在 HTML 中调整图 ...

  8. ubuntu 连不上网怎么办?

    [简洁版本] ctrl+alt+delete -> 任务管理器 ->"服务"选项卡 -> 运行"VMnet""VMware" ...

  9. Mysql8.0修改lower_case_table_names参数导致重启失败

    GreatSQL社区原创内容未经授权不得随意使用,转载请联系小编并注明来源. GreatSQL是MySQL的国产分支版本,使用上与MySQL一致. 事件起因:在测试一个数据迁移工具时,源端oracle ...

  10. kubeadm部署k8s v1.19.4版本集群

    1. 准备2台2c4g虚机 配置地址192.168.198.144,192.168.198.146,一台作为master,一台作为node 2. 部署环境准备,每一台虚机都需要操作 # 关闭防火墙sy ...