1.背景

作用:防止请求参数篡改,限制请求时效性;

常用方式:md5签名

关键:签名Key

常用签名原串排列:字母顺序、key1=value1&key2=value2....key (注意:签名规则是双方协商好,不一定是这个规则,这里只是以常规规则举例)

常用排序实现方式,利用TreeMap,进行排序,或者Arrays.sort先对key排序,然后根据key的顺序取值.

具体实现方案:aop统一接口签名

统一签名aop代码如下:

package com.ldp.user.common.aop;

import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.extra.servlet.ServletUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ldp.user.common.exception.ParamException;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes; import javax.servlet.http.HttpServletRequest;
import java.util.Map;
import java.util.TreeMap; /**
* @Copyright (C) XXXXX技有限公司
* @Author: lidongping
* @Date: 2020-12-16 18:36
* @Description: <p>
* 接口签名检查aop
* </p>
*/
@Slf4j
@Aspect
@Component
@SuppressWarnings("all")
public class SignAspect {
private static final String MD5_KEY = "123456"; /**
* 切入控制层
*/
@Pointcut("execution(* com.ldp.user.controller.*Controller.*(..))")
public void controllerAspect() {
} /**
* 切入控制层基类
*/
@Pointcut("execution(* com.ldp.user.common.base.BaseController.*(..))")
public void baseControllerAspect() {
} @Before("controllerAspect() || baseControllerAspect()")
private void before(JoinPoint joinPoint) {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
// json格式请求的参数
String params = ServletUtil.getBody(request);
if (StrUtil.isEmpty(params)) {
// key-value请求参数
Map<String, String> paramMap = ServletUtil.getParamMap(request);
params = JSONObject.toJSONString(paramMap);
}
// 签名检查
checkSign(params);
} /**
* 签名验证的作用: 防止参数篡改
* <p>
* 签名规则:
* 1. 除sign字段外,所有(有值的字段)字段按照字母顺序的"key1=value1&key2=value2&.....keyn=valuen"格式排序,等到str
* 2. str拼接上MD5_KEY,得到strMd5签名原串
* 3. 对strMd5字符串签名,得到strSign签名串
* <p>
* 案例
* 请求原数据: { "buyAccount": "wx001", "orderNo": "LDP003", "price": 6990, "productName": "苹果手机", "sign":"06282c01753c2d0b6d45491798b29de5"}
* 签名key: 123456
* 签名原串: buyAccount=wx001&orderNo=LDP003&price=6990&productName=苹果手机123456
* 签名值: 06282c01753c2d0b6d45491798b29de5
* 用户签名值: 06282c01753c2d0b6d45491798b29de5
* <p>
* 签名值可以在线生成校验
* 在线md5签名链接: https://md5jiami.51240.com/
*
* @param params
* @throws ParamException
*/
public void checkSign(String params) throws ParamException {
JSONObject jsonObject = JSON.parseObject(params);
// 有参数才检查签名
if (jsonObject == null || jsonObject.size() == 0) {
return;
}
// 准备sign
String sign = jsonObject.getString("sign");
if (StrUtil.isEmpty(sign)) {
throw new ParamException("签名值为空");
}
// 删除json中的sign
jsonObject.remove("sign");
// 准备签名字符串
StringBuilder sb = new StringBuilder();
// TreeMap能够根据key按照字典排序
Map<String, Object> map = new TreeMap(jsonObject);
// 遍历排序的字典,并拼接"key1=value1&key2=value2&.....keyn=valuen"格式
for (Map.Entry<String, Object> entry : map.entrySet()) {
Object value = entry.getValue();
String key = entry.getKey();
if (value == null || StrUtil.isEmpty(value.toString())) {
continue;
}
if ("".equals(sb.toString())) {
sb.append(key + "=").append(value.toString());
} else {
sb.append("&" + key + "=").append(value.toString());
}
}
String strMd5 = sb.toString() + MD5_KEY;
String md5 = SecureUtil.md5(strMd5);
log.info("请求原数据:" + params);
log.info("签名key:" + MD5_KEY);
log.info("签名原串:" + strMd5);
log.info("签名值:" + md5);
log.info("用户签名值:" + sign);
String lowerCase = sign.toLowerCase();
if (!lowerCase.equals(md5)) {
throw new ParamException("签名失败");
}
log.info("签名成功");
}
}

面试点:我们经常说面试时知识点要结合实际生产,那么,

如果面试官问了你关于map相关的知识点后,你是不是可以举例说比如在签名的时候我们可以使用TreeMap对签名原串进行排序的实际生产应用案例;

如果问到关于aop的技术点的时候,你可以说比如api接口统一签名使用aop实现的案例.....

这样可以大大提升你在面试官心目中的实践能力.....

如果你还是对这些不是很理解,可以看讲解视频,里面会详细介绍签名的原理、为什么可以防止请求参数篡改、具体实现方案等。

2.MD5简介

MD5加密全程是Message-Digest Algoorithm 5(信息-摘要算法),它对信息进行摘要采集,再通过一定的位运算,最终获取加密后的MD5字符串。

例如我们要加密一篇文章,那么我们会随机从每段话或者每行中获取一个字,把这些字统计出来后,再通过一定的运算获得一个固定长度的MD5加密后信息。

因此,其很难被逆向破解。

3.MD5算法具有以下特点

1、压缩性:任意长度的数据,算出的MD5值长度都是固定的。

2、容易计算:从原数据计算出MD5值很容易。

3、抗修改性:对原数据进行任何改动,哪怕只修改1个字节,所得到的MD5值都有很大区别。

4、弱抗碰撞:已知原数据和其MD5值,想找到一个具有相同MD5值的数据(即伪造数据)是非常困难的。

5、强抗碰撞:想找到两个不同的数据,使它们具有相同的MD5值,是非常困难的。

MD5的作用是让大容量信息在用数字签名软件签署私人密钥前被”压缩”成一种保密的格式(就是把一个任意长度的字节串变换成一定长的十六进制数字串)。

除了MD5以外,其中比较有名的还有sha-1、RIPEMD以及Haval等。

4.MD5是不可逆性

在讲解MD5签名原理之前,必须明白MD5是不可逆的,也就是不可破解的,

当然可能稍有了解的人会说MD5可以破解,

网上也有一些强大的数据库会把各种数据组合的MD5收集起来形成强大的数据库,

在数据库搜索可能一些简单的数据会马上找出某些组合对应的MD5值,

但咱说的MD5签名生成是最少32位的数值MD5加密,

所以这个破解的可能性是非常非常非常小的。所以这还是比较安全的。

5.原理

原理很简单,请求方对请求数据按一定的规则排序,加上appkey码一起通过MD5加密生成签名,

然后把请求数据和签名发给服务方,服务方拿到数据后,去掉无用的数据(值为空不一般不参与签名,或其他约定好了不签名的字段),

通过appid找到请求方的appkey,然后按同样的规则处理数据,并加上appkey通过MD5加密也生成签名,然

后和请求方生成的签名去对比,如果值一样,签名验证通过。

6.需要约定的数据

服务商一般会给你一个appid,appkey;

同时这两个参数服务商也会保存,这两个形成了你的唯一标识。

appid通过网络传输,而appkey是不在网络上进行传输的,只在生成签名时使用,所以安全性还是比较高的。

7.MD5生成签名的流程

1. 除去空值和签名值或其他约定不签名的值

2. 把参数字典排序,按照“参数=参数值”的模式用“&”字符拼接成字符串

3. 加上appkey值,对形成的数据进行MD5加密,生成签名

8.验证签名

1.验证签名时与生成签名时逻辑一样,将生成的签名进行比对

2.值得注意的是,很多签名带了时间戳参数,请求参数有时效性

即:就是算一个正确的签名也只能在30秒以内有效,这样可以防止对签名的破解

最后

这只是常规的签名做法,具体的签名规则和签名方式很多时候由双方协定好就可以了

但是建议大家在使用签名时,使用常规签名规则这样有很多好处......毕竟这是实际生产的经验.....也是很多人属性的规则,这样效率高得多

完美!

MD5签名生成,字典排序,实际生产的更多相关文章

  1. 签名:实现参数字典排序,然后拼接为url参数形式

    在很多地方请求参数需要做处理例如: 步骤 1.参数字典排序. 2.拼接字符. /// <summary> /// 生成签名 /// </summary> /// <par ...

  2. 接口签名进行key排序,并MD5加密

    import org.apache.commons.codec.digest.DigestUtils; import java.io.UnsupportedEncodingException; imp ...

  3. postman发送HTTP请求自动生成MD5签名

    POSTMAN是常用的接口测试工具 如何进行MD5签名呢? 代码如下: /** * 通过request.data获取body的内容,这个是postman内置变量 * 常用内置参数如下: * reque ...

  4. java生成32的md5签名串

    import java.security.MessageDigest; import lombok.extern.slf4j.Slf4j; /** * 签名帮助类 * * @author yangzl ...

  5. java学习-排序及加密签名时数据排序方式

    排序有两种 1. 类实现comparable接口调用List.sort(null)或Collections.sort(List<T>)方法进行排序 jdk内置的基本类型包装类等都实现了Co ...

  6. C# 字典排序Array.Sort

    Array.Sort可以实现便捷的字典排序,但如果完全相信他,那么就容易产生些异常!太顺利了,往往是前面有坑等你. 比如:微信接口,好多地方需要签名认证,签名的时候需要用的字典排序,如果只用Array ...

  7. 【Golang 接口自动化06】微信支付md5签名计算及其优化

    前言 可能看过我博客的朋友知道我主要是做的支付这一块的测试工作.而我们都知道现在比较流行的支付方式就是微信支付和支付宝支付,当然最近在使用低手续费大力推广的京东金融(已改名为京东数科)以后也可能站到第 ...

  8. python实例:元组命名 频次统计 字典排序

    1.为元组中元素命名 方法1.定义常量 NAME, AGE = 0, 1 student = ('乔峰', 29, 'qf@jinyong.com') name = student[NAME] age ...

  9. day3--集合、文件操作、字符编码与转换、函数(递归,lambda,filter,map)、字典排序

    list1 = set([1, 2, 3, 4, 5, 6, 5, 5, 5])list2 = set([11, 2, 36, 'a', 5, 6, 5, 5, 5])list3 = set([1, ...

  10. python进阶--字典排序

    zip()函数 sorted() 要求对字典中,按值的大小排序 解决方案: 利用zip函数 zip函数介绍: zip函数可以将可迭代对象打包成一个个元组,在python3中返回一个对象,在python ...

随机推荐

  1. MySQL BETWEEN AND包含边界值

    select count(1) from table_a where my_date between '20230715' and '20230717'; 上面的SQL我们发现只统计了20230715 ...

  2. 增补博客 第二篇 python 谢宾斯基三角型字符分形图形输出

    SIZE = int(input())# 输入分割次数 SIZE = SIZE<<3 # 将分割次数转为次数 y = SIZE - 1 # 用来控制列数 while y>=0: fo ...

  3. discuz论坛个人空间自定义css样式

    Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` discuz论坛个人空间自定义css样式 日期:2020- ...

  4. hdfs修复块

    磁盘满了一次,导致hdfs的很多块变成一个副本 看一下副本信息 执行 hdfs fsck / 1007个块少于3个副本一下  而且 hbase的regionsever启动报错 File /apps/h ...

  5. python selenium UI自动化操作iframe及返回默认页面

    页面操作的场景:进到到页面A,选择页面A里面的记录,点击签约, 弹出一个弹窗B,弹窗B的内容是协议及同意按钮或其他非同意的提示信息,主要的操作,打开页面A,点击签约,点击同意,操作完成 分析页面的组成 ...

  6. 忘记Linux密码这样破解

    忘记了Linux的密码该怎么办呢?有人想到重装系统.我想说除非你不想干了! 在这里使用CentOS7来教大家怎么 破解Linux的密码 (不能知道原来的密码,但是可以强行修改) 1.在grub引导界面 ...

  7. 【读论文】CM-Gen: A Neural Framework for Chinese Metaphor Generation with Explicit Context Modelling

    为了更好的阅读体验,请点击这里 由于发不出论文,所以找点冷门方向做一做.从汉语比喻开始. 读完这篇论文之后我觉得 COLING 这方向我上我也行(ε=ε=ε=┏(゜ロ゜;)┛ 题目:CM-Gen: A ...

  8. C# pythonnet(2)_傅里叶变换(FFT)

    Python代码如下 import pandas as pd import numpy as np import matplotlib.pyplot as plt # 读取数据 data = pd.r ...

  9. 仓颉语言HelloWorld内测【仅需三步】

    2024年6月21日,华为仓颉正式公开发布.还记的19年和王学智的团队做过接触,他们反馈说16年我出版的<自己动手构造编译系统>一书对他们的研发很有帮助,身为作者听到这个消息还是很开心的. ...

  10. 【ClickHouse】7:clickhouse多实例安装

    背景介绍: 有三台CentOS7服务器安装了ClickHouse HostName IP 安装程序 实例1端口 实例2端口 centf8118.sharding1.db 192.168.81.18 c ...