通用 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
{
/// <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 签名组件的另类实现的更多相关文章
- ASP.NET通用权限验证组件实现
沙发(SF)通用权限验证组件 开篇 本篇介绍通用权限验证的实现代码思路,总共分为导入参数.解析XML.根据XML配置进行处理.返回结果. 代码架构图 1. 类介绍 1.SFWebPermissio ...
- SNFAutoupdater通用自动升级组件V2.0
1.组件介绍 C/S构的特点是能充分发挥客户端的处理能力,很多工作可以由客户端处理后再提交给服务器,对应的优点就是客户端响应速度快模式客户端以其强大的功能,丰富的表现力受到相当大部分用户的青睐,但是客 ...
- 如何通过 Vue+Webpack 来做通用的前端组件化架构设计
目录: 1. 架构选型 2. 架构目录介绍 3. 架构说明 4. 招聘消息 目前如果要说比较流行的前端架构哪家强,屈指可数:reactjs.angularjs.emberj ...
- 给 Web 开发人员推荐的通用独立 UI 组件(二)
现代 Web 开发在将体验和功能做到极致的同时,对于美观的追求也越来越高.在推荐完图形库之后,再来推荐一些精品的独立 UI 组件.这些组件可组合在一起,形成美观而交互强大的 Web UI . 给 We ...
- Blazor组件自做二 : 使用JS隔离制作手写签名组件
Blazor组件自做二 : 使用JS隔离制作手写签名组件 本文相关参考链接 JavaScript 模块中的 JavaScript 隔离 Viewer.js工程 Blazor组件自做一 : 使用JS隔离 ...
- Blazor组件自做四 : 使用JS隔离封装signature_pad签名组件
运行截图 演示地址 响应式演示 感谢szimek写的棒棒的signature_pad.js项目, 来源: https://github.com/szimek/signature_pad 正式开始 1. ...
- 《Nodejs开发加密货币》之二十七:开发通用的HTML组件
人的懒惰常常是麻烦的开始.多数程序员都希望自己的工作一劳永逸,一次开发,到处使用,成了人人追逐的目标,我也不例外.最初写<Nodejs开发加密货币>系列文章,因为不喜欢设定好了去写,所以目 ...
- Tsx写一个通用的button组件
一年又要到年底了,vue3.0都已经出来了,我们也不能一直还停留在过去的js中,是时候学习并且在项目中使用一下Ts了. 如果说jsx是基于js的话,那么tsx就是基于typescript的 废话也不多 ...
- 容器扩展属性 IExtenderProvider 实现WinForm通用数据验证组件
大家对如下的Tip组件使用应该不陌生,要想让窗体上的控件使用ToolTip功能,只需要拖动一个ToolTip组件到窗口,所有的控件就可以使用该功能,做信息提示. 本博文要记录的,就是通过容器扩展属性 ...
随机推荐
- LCA——树上倍增
首先,什么是LCA? LCA:最近公共祖先 祖先:从当前点到根节点所经过的点,包括他自己,都是这个点的祖先 A和B的公共祖先:同时是A,B两点的祖先的点 A和B的最近公共祖先:深度最大的A和B的公共祖 ...
- Cow Picnic S
题目描述: K(1≤K≤100)只奶牛分散在N(1≤N≤1000)个牧场.现在她们要集中起来进餐.牧场之间有M(1≤M≤10000)条有向路连接,而且不存在起点和终点相同的有向路.她们进餐的地点必须是 ...
- CF242E XOR on Segment
CF242E XOR on Segment codeforces 洛谷 关于异或,无法运用懒标记实现区间异或: 可以像trie树一样拆位,将每个值拆成二进制数,对此建相应个数的线段树. 0 1与 0异 ...
- React报错之react component changing uncontrolled input
正文从这开始~ 总览 当input的值被初始化为undefined,但后来又变更为一个不同的值时,会产生"A component is changing an uncontrolled in ...
- 【面试题】纯css实现三角形,你知道如何实现吗?
纯css实现三角形 点击打开视频教程 <template> <div id="app"> <!-- 纯css实现三角形书写 --> <di ...
- JUC源码学习笔记5——线程池,FutureTask,Executor框架源码解析
JUC源码学习笔记5--线程池,FutureTask,Executor框架源码解析 源码基于JDK8 参考了美团技术博客 https://tech.meituan.com/2020/04/02/jav ...
- C# 使用SIMD向量类型加速浮点数组求和运算(1):使用Vector4、Vector<T>
作者: 目录 一.缘由 二.使用向量类型 2.1 基本算法 2.2 使用大小固定的向量(如 Vector4) 2.2.1 介绍 2.2.2 用Vector4编写浮点数组求和函数 2.3 使用大小与硬件 ...
- 入门 Socket.io
概念 Socket.io 是一个支持客户端和服务器之间的低延迟.双向和基于事件的通信的库,除了支持 JavaScript 以外,还支持 Java.Python.Golang. Socket.io 构建 ...
- Canvas 非常重要的三个函数
beginPath 绘制路径必须添加 beginPath().它标志着一个画笔在画布中哪个地方开始画起.没有它,新起的画笔位置必定与上一次画笔结束的位置相连. // 第一个半圆 ctx.arc(60, ...
- ansible 的安装及常见模块使用
ansible 基础keys的ssh协议配置的 特性:幂等性:一个任务执行1遍和执行n遍效果一样. ansible是个管理软件不是服务,不需要长期运行 一.通过epel源安装ansible, 1.下 ...