WebAPI 用户认证防篡改实现HMAC(一)MD5签名获取
来源:互联网 发布:淘宝发布宝贝不同价格 编辑:程序博客网 时间:2024/05/17 21:39
在开始前先说下HMAC防篡改机制的原理,如果已经接触过支付宝的可以跳过此部分
防篡改,顾名思义就是防止有人恶意篡改请求数据以达到恶意攻击的目的,那要怎么才能实现这样的目的呢?其实很简单,将要请求的数据加上合作号、合作Key按规则组织成一个字符串,获取对应的MD5摘要,然后将该摘要及合作号同时作为请求的一部分一起传递(合作Key禁止传递)
下面进行举例:
假定需要进行签名的参数如下(以json格式举例):
{‘partner’: ‘3122131212’,‘orderNo’:‘1234567’}
对数组里的每一个键按默认的字母正向排序,最后加上partner对应的key进行MD5加密,假定对应的key为bbb,则需要进行MD5摘要的字符串如下:
partner=3122131212&orderNo=1234567bbb
最终需要传递的请求数据格式如下(分别列举GET和POST方式,服务实际支持哪种方式以服务声明为准):
GET:partner=3122131212&orderNo=1234567&sign=EBFE84D02E8E40952899EE5CDFE5404C
POST
:
{‘partner’:‘3122131212’,‘orderNo’:‘1234567’ ,‘sign:‘EBFE84D02E8E40952899EE5CDFE5404C
’}
上例中partner为平台提供的合作号,key为合作密码,sign为签名,然后此处例子是将Get和Post区分开来的,实际获取MD5的代码会支持QueryString及Form同时存在的情况,且当两者同时存在时,组织字符串顺序为先QueryString后Form
以下是签名摘要生成代码
- using System;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.Security.Cryptography;
- using System.Text;
- public static class SecuritySignHelper
- {
- public const string Partner = "partner";
- public const string Sign = "sign";
- /// <summary>
- /// 获取防篡改签名,组织原始字符串的方式为:先get后post,该签名要求partner在加密时为全小写,同时该方法隐含要求parnter和sign必须通过QueryString方式传递
- /// </summary>
- /// <param name="getCollection">通过QueryString方式传递的键值集合,如果内部包含parnter或者sign,相关字段在组织原始字符串时将会被移除</param>
- /// <param name="partner">合作账号</param>
- /// <param name="partnerKey">合作Key</param>
- /// <param name="postCollection">通过Form方式传递的键值集合,如果包含parnter或者sign,此部分不会被做特殊处理</param>
- /// <returns></returns>
- public static string GetSecuritySign(this NameValueCollection getCollection, string partner, string partnerKey, NameValueCollection postCollection = null)
- {
- if (string.IsNullOrWhiteSpace(partner) || string.IsNullOrWhiteSpace(partnerKey))
- {
- throw new ArgumentNullException();
- }
- var dic = SecuritySignHelper.GetSortedDictionary(getCollection,
- (k) =>
- {//过滤partner及sign
- return string.Equals(k, SecuritySignHelper.Partner, StringComparison.OrdinalIgnoreCase)
- || string.Equals(k, SecuritySignHelper.Sign, StringComparison.OrdinalIgnoreCase);
- });
- dic.Add(SecuritySignHelper.Partner, partner);
- StringBuilder tmp = new StringBuilder();
- SecuritySignHelper.FillStringBuilder(tmp, dic);//将QueryString填入StringBuilder
- dic = SecuritySignHelper.GetSortedDictionary(postCollection);
- SecuritySignHelper.FillStringBuilder(tmp, dic);//将Form填入StringBuilder
- tmp.Append(partnerKey);//在尾部添加key
- tmp.Remove(0, 1);//移除第一个&
- return tmp.ToString().GetMD5_32();//获取32位长度的Md5摘要
- }
- private static SortedDictionary<string, string> GetSortedDictionary(NameValueCollection collection, Func<string, bool> filter = null)
- {//获取排序的键值对
- SortedDictionary<string, string> dic = new SortedDictionary<string, string>();
- if (collection != null && collection.Count > 0)
- {
- foreach (var k in collection.AllKeys)
- {
- if (filter == null || !filter(k))
- {//如果没设置过滤条件或者无需过滤
- dic.Add(k, collection[k]);
- }
- }
- }
- return dic;
- }
- private static void FillStringBuilder(StringBuilder builder, SortedDictionary<string, string> dic)
- {
- foreach (var kv in dic)
- {
- builder.Append('&');
- builder.Append(kv.Key);
- builder.Append('=');
- builder.Append(kv.Value);
- }//按key顺序组织字符串
- }
- /// <summary>
- /// 获取32位长度的Md5摘要
- /// </summary>
- /// <param name="inputStr"></param>
- /// <param name="encoding"></param>
- /// <returns></returns>
- public static string GetMD5_32(this string inputStr, Encoding encoding = null)
- {
- RefEncoding(ref encoding);
- byte[] data = GetMD5(inputStr, encoding);
- StringBuilder tmp = new StringBuilder();
- for (int i = 0; i < data.Length; i++)
- {
- tmp.Append(data[i].ToString("x2"));
- }
- return tmp.ToString();
- }
- private static byte[] GetMD5(string inputStr, Encoding encoding)
- {
- using (MD5 md5Hash = MD5.Create())
- {
- return md5Hash.ComputeHash(encoding.GetBytes(inputStr));
- }
- }
- private static void RefEncoding(ref Encoding encoding)
- {
- if (encoding == null)
- {
- encoding = Encoding.Default;
- }
- }
- }
- string partner = "zhangsan";
- string partnerKey = "bbb";
- NameValueCollection getCollection = new NameValueCollection();
- string md50 = getCollection.GetSecuritySign(partner, partnerKey);//不带任何参数的请求
- getCollection.Add("test", "123");
- string md51 = getCollection.GetSecuritySign(partner, partnerKey);//带一个参数的请求
- NameValueCollection postCollection = new NameValueCollection();
- postCollection.Add("Name", "张三");
- postCollection.Add("Address", "上海");
- string md52 = getCollection.GetSecuritySign(partner, partnerKey, postCollection);//同时存在QueryString及Form的请求
- WebAPI 用户认证防篡改实现HMAC(一)MD5签名获取
- WebAPI 用户认证防篡改实现HMAC(一)MD5签名获取
- WebAPI 用户认证防篡改实现HMAC(二)签名验证 AbsBaseAuthenticationAttribute
- WebAPI 用户认证防篡改实现HMAC(四)ApiController
- WebAPI 用户认证防篡改实现HMAC(三)异常信息处理 AbsCommonExceptionFilterAttribute
- WebAPI 用户认证防篡改实现HMAC(五)测试小工具 SecuritySignTool
- Unity笔记 XML读写 防篡改MD5签名
- HMAC-SHA1签名认证算法
- Java中使用 Md5+Key的方式对Url签名防篡改
- Android数据传输增加签名认证(防止数据被篡改)
- Android 获取HMAC-MD5 加密
- url增加签名验证防篡改
- HMAC-MD5的C#实现
- java实现HMAC-MD5算法
- WebApi系列~安全校验中的防篡改和防复用
- 如何实现网页防篡改
- 使用数字签名实现数据库记录防篡改(Java实现)
- 使用数字签名实现数据库记录防篡改(Java实现)
- 分析iOS Crash文件:符号化iOS Crash文件的3种方法
- 手机端页面 输入法覆盖输入框问题
- 数组内元素按字母顺序排序,字典的key按字母顺序排列
- swift简单学习之逻辑运算符
- Ubuntu 14.04 LTS 使用sudo免输密码
- WebAPI 用户认证防篡改实现HMAC(一)MD5签名获取
- iOS开发 CocoaPods 的安装流程
- 【笔记】《C#大学教程》- 第11章 异常处理
- 209. Minimum Size Subarray Sum LeetCode
- 不带温度补偿的DIMU校准
- Java高级开发工程师考纲
- 排序算法-快速排序
- 内存泄漏——1.基础知识篇
- strtus2基本学习记录