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. 优雅哥学 Webpack - 01 - Webpack 5 快速体验

    程序员优雅哥简介:十年程序员,呆过央企外企私企,做过前端后端架构.分享vue.Java等前后端技术和架构 本文摘要:主要讲解 webpack 5 初体验.从webpack 5 初识到便写代码.优雅哥将 ...

  2. python操作ini文件

    简介 ini文件作为常见的配置文件,因此需要对ini文件做处理,此处使用configparser模块,本文介绍以下ini文件常用的处理方式. 需要读取的ini文件 如下文件,[ ]包含的称为secti ...

  3. v-model原理问题

    v-model的原理 很多同学在理解Vue的时候都把Vue的数据响应原理理解为双向绑定,但实际上这是不准确的,我们之前提到的数据响应,都是通过数据的改变去驱动DOM重新的变化,而双向绑定已有数据驱动D ...

  4. 【原创】Python 二手车之家车辆档案数据爬虫

    本文仅供学习交流使用,如侵立删! 二手车之家车辆档案数据爬虫 先上效果图 环境 win10 python3.9 lxml.retrying.requests 需求分析 需求: 主要是需要车辆详情页中车 ...

  5. 巨细靡遗流程控制,Go lang1.18入门精炼教程,由白丁入鸿儒,Go lang流程结构详解EP09

    流程结构就是指程序逻辑到底怎么执行,进而言之,程序执行逻辑的顺序.众所周知,程序整体都是自上由下执行的,但有的时候,又不仅仅是从上往下执行那么简单,大体上,Go lang程序的流程控制结构一共有三种: ...

  6. Java开发学习(二十五)----使用PostMan完成不同类型参数传递

    一.请求参数 请求路径设置好后,只要确保页面发送请求地址和后台Controller类中配置的路径一致,就可以接收到前端的请求,接收到请求后,如何接收页面传递的参数? 关于请求参数的传递与接收是和请求方 ...

  7. 将 Word 文本转换为表格

    文本转换为表格的功能,首先点击"插入"选项卡"表格"组中的"表格"下拉按钮,打开下拉列表中选择"文本转换成表格"选项.

  8. Web 前端实战:Gitee 贡献图

    前言 这次要做的 Web 前端实战是一个 Gitee 个人主页下的贡献图(在线 Demo),偶尔做一两个,熟悉熟悉 JS 以及 jQ.整体来说这个案例并不难,主要是控制第一个节点以及最后一个节点处于星 ...

  9. Excel 统计函数(六):RANK

    [语法]RANK(number,ref,[order]) [参数] number:要找到其排位的数字. ref:数字列表的数组,对数字列表的引用.Ref 中的非数字值会被忽略. order:一个指定数 ...

  10. 年轻的樵夫哟,你掉的是这个免费 8 核 4G 公网Docker 服务器

    Play With Docker 直接打开 https://labs.ply-with-docker.com/ 即可访问 Play With Docker 平台. 注册一个 DockerHub 账号便 ...