WEB API 接口签名sign验证入门与实战
目录
- 参考
- 什么是加解密
- 加密方式分类
- 对称加密技术
- 非对称加密技术(RSA加密算法)(数字证书)
- 场景1:公钥加密,私钥解密
- 场景2:秘钥加密:数字签名,公钥解密:验证签名
- MD5(完全不考虑解密,也叫哈希算法,散列算法)
- Postman
- Jmeter
- 接口签名sign原理
- 什么是接口签名
- 为什么做接口签名
- 如何做接口签名
- 对所有参数按key按ASCⅡ码做升序排序
- 把参数名和参数值连接成字符串
- 把申请到的appKey和appSecret连接到字符串的头部
- 用时间戳连接到字符串的尾部,可以增加失效检测
- 增加随机数nonstr防止重放攻击
- 把上述字符串进行md5加密
- 常见签名算法示例
- 示例1
参考
B站讲的最好的接口加密解密以及接口签名sign原理
什么是加解密
加密:在网络上传输的原始数据(明文)经过加密算法加密后形成(密文)传输,防止被窃取
解密:将密文还原成原始数据
加密方式分类
对称式加密:对加密和解密使用同一个秘钥
非对称加密:非对称式加密需要两个秘钥(双钥),分别叫公钥和秘钥,这两把秘钥可以相互加解密。公钥公开的,不需要保密,而私钥是保密的。
对称加密技术
- DES加密算法
- AES加密算法
- Base64算法
可以在https://www.bejson.com/enc/aesdes/体验
des和aes每次加密之后密文不一样,而Base64加密之后密文固定
非对称加密技术(RSA加密算法)(数字证书)
通过网站https://www.bejson.com/enc/rsa/在线生成公钥和私钥,并且可以进行公钥加密和私钥解密测试
场景1:公钥加密,私钥解密
两个用户:A和B,B有双钥;A想把一个数据报文通过加密方式发给B
场景2:秘钥加密:数字签名,公钥解密:验证签名
数字证书由来:由于公钥是公开的不安全,所以需要第三方的CA(数字证书颁发机构),对公钥加密,加密后的东西就叫数字证书。
数字证书包括:B用户基本信息及B的公钥的信息。X509的标准
CA:双钥,通过私钥加密
Fiddler不能直接抓取https协议的数据报文,需要安装一个数字证书
https = http + ssl安全传输协议
ssl安全传输协议:安全套接层,NetScape研发
MD5(完全不考虑解密,也叫哈希算法,散列算法)
Postman
Jmeter
${__digest(MD5,admin,)}
接口签名sign原理
什么是接口签名
接口签名:使用用户名,密码,时间戳和所有的排过序之后的参数组合起来,再加密得到的字符串,字符串是唯一的有权访问接口的鉴权码
用户名:appKey
密码:appSecret
为什么做接口签名
- 防伪装攻击
- 防篡改攻击
- 防重放攻击
- 防数据泄露
保证访问者的合法性。保证参数不被修改,确保请求的唯一性
如何做接口签名
对所有参数按key按ASCⅡ码做升序排序
比如参数是?c=1&b=2&a=3
排序之后是a,b,c
把参数名和参数值连接成字符串
a=1&b=2&c=3
把申请到的appKey和appSecret连接到字符串的头部
appKey=admin&appSecret=123&a=1&b=2&c=3
用时间戳连接到字符串的尾部,可以增加失效检测
比如1分钟内有效
appKey=admin&appSecret=123&a=1&b=2&c=3×tamp=1666757432136
增加随机数nonstr防止重放攻击
nonstr可以是随机数,最好是uuid
appKey=admin&appSecret=123&a=1&b=2&c=3×tamp=1666757432136&nonstr=123123
把上述字符串进行md5加密
String str = "appKey=admin&appSecret=123&a=1&b=2&c=3×tamp=1666757432136&nonstr=123123";
String sign = md5(str);
常见签名算法示例
示例1
签名算法
签名算法描述如下:
1.将请求参数按参数名升序排序;
2.按请求参数名及参数值相互连接组成一个字符串:…;
3.将应用密钥分别添加到以上请求参数串的头部和尾部:<请求参数字符串>;
4.对该字符串进行MD5(全部大写),MD5后的字符串即是这些请求参数对应的签名;
5.该签名值使用sign参数一起和其它请求参数一起发送给服务开放平台。
伪代码:
Map<String,Object> paramsMap = new ...; // 参数Set<String> keySet = paramsMap.keySet();
List<String> paramNames = new ArrayList<String>(keySet);
// 1.
Collections.sort(paramNames);StringBuilder paramNameValue = new StringBuilder();
// 2.
for (String paramName : paramNames) {paramNameValue.append(paramName).append(paramsMap.get(paramName));
}
// 3.
String source = secret + paramNameValue.toString() + secret;
// 4.
String sign = md5(source);
// 5.
paramsMap.put("sign",sign);
代码示例
import java.io.IOException;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;import org.junit.Test;import com.alibaba.fastjson.JSON;import junit.framework.TestCase;public class PostTest extends TestCase {@Testpublic void testPost() throws IOException {String appKey = "xxx";String secret = "xxx";// 业务参数Map jsonMap = new HashMap();jsonMap.put("dicCode", "terminalType");String json = JSON.toJSONString(jsonMap);json = URLEncoder.encode(json, "utf-8");// 系统参数Map param = new HashMap();param.put("name", "dictionaryItem.list");param.put("version", "1.0");param.put("app_key", appKey);param.put("data", json);param.put("timestamp", getTime());param.put("format", "json");String sign = buildSign(param, secret);param.put("sign", sign);/*// 最终请求数据{"name":"dictionaryItem.list","version":"1.0","app_key":"test","data":"%7B%22dicCode%22%3A%22terminalType%22%7D","timestamp":"2021-12-15 10:25:02","format":"json","sign":"4B291FFFFDD6F0E3FB9708AC0F7AC334"}*/System.out.println("=====请求数据=====");String postJson = JSON.toJSONString(param);System.out.println(postJson);// contentType:application/json// postJson放到请求体中// 发送请求String resp = HttpRequest.post("https://xxx.net/api").body(postJson).execute().body();System.out.println(resp);/*响应结果:{"code":"0","data":[{"dicCode":"terminalType","isplay":1,"itemId":120,"itemName":"音柱/音箱","itemValue":"1","sort":1},{"dicCode":"terminalType","isplay":1,"itemId":121,"itemName":"AIO报警箱","itemValue":"2","sort":2},{"dicCode":"terminalType","isplay":1,"itemId":122,"itemName":"融媒体客服主机","itemValue":"3","sort":3},{"dicCode":"terminalType","isplay":1,"itemId":123,"itemName":"网络调音台","itemValue":"4","sort":4},{"dicCode":"terminalType","isplay":1,"itemId":124,"itemName":"云广播适配器","itemValue":"5","sort":5},{"dicCode":"terminalType","isplay":1,"itemId":125,"itemName":"音频编码器","itemValue":"6","sort":6},{"dicCode":"terminalType","isplay":1,"itemId":126,"itemName":"村级播控主机","itemValue":"7","sort":7},{"dicCode":"terminalType","isplay":1,"itemId":127,"itemName":"云话筒","itemValue":"8"},{"dicCode":"terminalType","isplay":1,"itemId":128,"itemName":"安卓手机客户端","itemValue":"9"},{"dicCode":"terminalType","isplay":1,"itemId":129,"itemName":"收扩机","itemValue":"10","sort":8}]}*/}/*** 构建签名** @param paramsMap* 参数* @param secret* 密钥* @return* @throws IOException*/public static String buildSign(Map<String, ?> paramsMap, String secret) throws IOException {Set<String> keySet = paramsMap.keySet();List<String> paramNames = new ArrayList<String>(keySet);Collections.sort(paramNames);StringBuilder paramNameValue = new StringBuilder();for (String paramName : paramNames) {paramNameValue.append(paramName).append(paramsMap.get(paramName));}String source = secret + paramNameValue.toString() + secret;return md5(source);}/*** 生成md5,全部大写** @param message* @return*/public static String md5(String message) {try {// 1 创建一个提供信息摘要算法的对象,初始化为md5算法对象MessageDigest md = MessageDigest.getInstance("MD5");// 2 将消息变成byte数组byte[] input = message.getBytes();// 3 计算后获得字节数组,这就是那128位了byte[] buff = md.digest(input);// 4 把数组每一字节(一个字节占八位)换成16进制连成md5字符串return byte2hex(buff);} catch (Exception e) {throw new RuntimeException(e);}}/*** 二进制转十六进制字符串** @param bytes* @return*/private static String byte2hex(byte[] bytes) {StringBuilder sign = new StringBuilder();for (int i = 0; i < bytes.length; i++) {String hex = Integer.toHexString(bytes[i] & 0xFF);if (hex.length() == 1) {sign.append("0");}sign.append(hex.toUpperCase());}return sign.toString();}/*** 十六进制字符串转二进制** @param hexString* @return*/private static byte[] hexStringToBytes(String hexString) {if (hexString == null || hexString.equals("")) {return null;}hexString = hexString.toUpperCase();int length = hexString.length() / 2;char[] hexChars = hexString.toCharArray();byte[] d = new byte[length];for (int i = 0; i < length; i++) {int pos = i * 2;d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));}return d;}/*** 二进制数据生成mp3音频文件** @param data 二进制数据* @param filePath 文件目录* @return*/public static String bytesToFile(byte[] data, String filePath) throws IOException {//方法一:直接生成文件String url = filePath + ".mp3";File file = new File(filePath);if (!file.exists()) {file.createNewFile();}FileOutputStream os = new FileOutputStream(file);os.write(data);//方法二:将二进制数据上传阿里云oss,生成文件//String url = "http://" + OSSFactory.build().uploadSuffix(data, ".mp3");return url;}public String getTime() {return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());}
}
WEB API 接口签名sign验证入门与实战相关推荐
- API接口签名生成算法和签名验证算法
1.参考网上资料和书本资料,实现了API接口签名生成算法和签名验证算法. (1)参考资料:https://www.jianshu.com/p/d47da77b6419 (2)参考书籍:高级软件架构师教 ...
- 软件测试 接口测试 接口鉴权 token鉴权 Mock Server 接口加解密 接口签名sign
文章目录 1 接口鉴权 1.1 cookie鉴权 1.2 session鉴权 1.3 token鉴权 1.4 Postman的鉴权方式 2 Mock Server 3 接口加解密 3.1 加密方式 3 ...
- API 接口签名验签
目录 一.为什么需要 API 接口签名 二.API 接口签名验签实现机制 一.为什么需要 API 接口签名 对外开放的 API 接口都会面临一些安全问题,例如伪装攻击.篡改攻击.重放攻击以及数据信息泄 ...
- Web API接口开发和测试
4.ASP.NET Web API的开发 上面我们定义了一般的Web API接口,以及实现相应的业务实现,如果我们需要创建Web API层,还需要构建一个Web API项目的. 创建好相应的项目后,可 ...
- Java API接口签名认证
Java API接口签名认证 我们在进行程序开发的时候,一定会开发一些API接口,供他人访问.当然这些接口中有可能是开放的,也有可能是需要登录才能访问的,也就是需要Token鉴权成功后才可以访问的.那 ...
- 不使用jQuery对Web API接口POST,PUT,DELETE数据
前些天,Insus.NET有演示Web API接口的操作: <怎样操作WebAPI接口(显示数据)>http://www.cnblogs.com/insus/p/5670401.html ...
- Spring Boot API 接口文档 Swagger 入门
转载自 芋道 Spring Boot API 接口文档 Swagger 入门 摘要: 原创出处 http://www.iocoder.cn/Spring-Boot/Swagger/ 「芋道源码」欢迎转 ...
- ASP.NET Web API 接口执行时间监控
软件产品常常会出现这样的情况:产品性能因某些无法预料的瓶颈而受到干扰,导致程序的处理效率降低,性能得不到充分的发挥.如何快速有效地找到软件产品的性能瓶颈,则是我们感兴趣的内容之一. 在本文中,我将解释 ...
- rap2检测哪些接口在使用_使用RAP2和Mock.JS实现Web API接口的数据模拟和测试
最近一直在思考如何对Web API的其接口数据进行独立开发的问题,随着Web API的越来越广泛应用,很多开发也要求前端后端分离,例如统一的Web API接口后,Winform团队.Web前端团队.微 ...
- 调用JShaman的Web API接口,实现JS代码加密。
在NodeJS中,调用JShaman的Web API接口,实现JS代码加密. 同样的方法,也可把该功能集成到自己的产品或项目中,让自己也具备JS加密功能. 调用JShaman接口的源码非常简单: /* ...
最新文章
- Altium Designer 18 怎么导出CAD文件
- 最短公共子序列_最短公共超序列
- [leetcode]Generate Parentheses
- Linux练习(函数调用复制文件)
- 什么是IDS/IPS?
- VMWare虚拟机Linux系统忘记登录密码
- 蓝牙解码格式哪个最好_柏韵Pureaudio AirDSD Pro 串流播放解码前级
- Electron 使用 regedit 控制注册表(实现win文件右键菜单)
- 诺顿杀毒软件22010最新注册码
- Context是什么
- Google Chrome 66可以下载啦
- android 点击状态栏,“点击状态栏回到顶部”功能的消失原因和实现
- 面向订单生产型电子制造企业,如何快速响应客户?
- 2023年五一数学建模竞赛ABC题思路资料汇总贴
- TOP Network 2019年度回顾:积蓄力量,再创辉煌
- javafx 订单项目源码_终于找到一个JavaFx开发的东西,pdf阅读器。包括源代码
- 【发车优化】基于遗传算法的公交车调度排班优化的研究与实现附Matlab代码
- SecureCRT乱码的问题
- 编写一个求定积分的通用函数
- Flutter IOS 新建打包发布全流程 2023 版
热门文章
- mysql实现pr曲线_如何画PR curve (PR曲线)基于COCO格式数据集 在maskrcnn_benchmark中
- java bs和cs_BS与CS的区别和联系
- 毕业论文格式系列---1.论文公式编号
- 湘源控规计算土石方流程
- python 文本处理(分割)
- 谷歌恐龙游戏HTML,谷歌浏览器小恐龙游戏
- oracle 索引优化
- navicat for mysql Mac版 中文免安装
- 浅谈 Java 24个设计模式(23个GoF设计模式 + 简单工厂模式) 之 六个创建型模式...
- (学习笔记)图像处理——Retinex增强