当前位置: 首页 > news >正文

springboot 基于签名的安全通信

背景:

接口安全通信:实现方案:
参考淘宝 https://open.taobao.com/doc.htm?spm=a219a.15212433.0.0.32ee669aSWyr5e&docId=101617&docType=1
推荐使用https通信,若数据包包含敏感信息,建议对数据包进行 sm4加密,可参考
https://blog.csdn.net/qq_26408545/article/details/149660016

原理:
1)双方约定签名的私钥,且一个应用一个签名的私钥
2)参数携带时间,并约定有效期
3)数据体固定格式:不能用是无序的map,且数据体内时间格式统一:"yyyy-MM-dd HH:mm:ss"
4)双方按照约定的方式进行签名与验签时间 与 签名 验证通过,方可进行业务操作

一:访问接口的实现

这里JSON序列化和摘要算法,用的hutool

<dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.38</version>
</dependency>

1 ApiEntity:公共的外层数据实体

import com.flowable.api.entity;import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;import java.io.Serial;
import java.io.Serializable;
import java.time.LocalDateTime;@Data
public class ApiEntity<T> implements Serializable {@Serialprivate static final long serialVersionUID = 1L;/*** 应用的id*/@NotEmpty(message = "应用的id不能为空")private String appId;/*** 请求最大时间误差为10分钟*/@NotNull(message = "请求时间不能为空")@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")private LocalDateTime timestamp;/*** 数据*/private T data;/*** 数据签名结果*/private String sign;
}

2 FlowApiController :接口实现的格式

package com.flowable.api.controller;import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.exceptions.ExceptionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import com.flowable.api.entity.ApiEntity;
import com.flowable.api.entity.dto.ProcessCancelDto;
import jakarta.validation.Valid;
import org.springframework.web.bind.annotation.*;import java.nio.charset.StandardCharsets;
import java.time.temporal.ChronoUnit;
import java.util.HashMap;
import java.util.Map;@RestController
@RequestMapping("/open/flow")
public class FlowApiController {/*** 取消流程实例** @param dto 请求参数*/@PostMapping("/cancel-instance")public void cancelProcessInstance(@Valid @RequestBody ApiEntity<ProcessCancelDto> dto) {// 1 验证请求参数validateParam(dto);// 2 执行流程取消// ... ;}// 因为这里 采用的hash512签名,签名密钥要大于64位public static final Map<String, String> appMap = new HashMap<>() {{// ERP 对接签名put("应用的id", "应用的签名密钥:要大于64位");}};/*** 验证请求基本格式** @param dto 请求公共参数*/public void validateParam(ApiEntity<?> dto) {// 1 计算当前时间与请求时间差,不超过10分钟long durationMinutes = LocalDateTimeUtil.between(LocalDateTimeUtil.now(), dto.getTimestamp(), ChronoUnit.MINUTES);if (Math.abs(durationMinutes) > 10L) {throw ExceptionUtil.wrapRuntime("请求时间超过许可范围!");}// 2 获取应用的 appSecretString appSecret = appMap.get(dto.getAppId());if (StrUtil.isEmpty(appSecret)) {throw ExceptionUtil.wrapRuntime("不能识别应用ID!");}// 3 配置json的日期格式JSONConfig jsonConfig = new JSONConfig();jsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");// 4 假设请求存在参数,数据转json 并校验数据摘要if (ObjectUtil.isNotNull(dto.getData())) {// 1 生成签名HMac hMac = DigestUtil.hmac(HmacAlgorithm.HmacSHA512, appSecret.getBytes(StandardCharsets.UTF_8));// 2 生成请求摘要if (!StrUtil.equals(hMac.digestHex(JSONUtil.toJsonStr(dto.getData(), jsonConfig)), dto.getSign())) {throw ExceptionUtil.wrapRuntime("数据验签不通过!");}}}}

3 ProcessCancelDto:用于构建测试的实体

该实体无关紧要,你可以改成任意你的业务实体

package com.flowable.api.entity.dto;import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.Size;
import lombok.Data;/*** 管理后台 - 流程实例的创建 Request dto* !!属性顺序、属性名称、属性类型 勿动,已接入其他系统*/
@Data
public class ProcessCancelDto {/*** 用户账号*/@Size(max = 64)@NotEmpty(message = "用户账号")private String userAccount;/*** 流程实例的编号*/@NotEmpty(message = "流程实例编号不能为空")private String id;/*** 取消原因*/private String reason;
}

二:请求方的数据构建

FlowableTest 测试类:其中的 ApiEntity、ProcessCancelDto 数据格式同上

package org.example;import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.crypto.digest.HMac;
import cn.hutool.crypto.digest.HmacAlgorithm;
import cn.hutool.json.JSONConfig;
import cn.hutool.json.JSONUtil;
import org.example.entity.ApiEntity;
import org.example.entity.dto.ProcessCancelDto;
import org.junit.Test;import java.nio.charset.StandardCharsets;
public class FlowableTest {/*** 测试流程部署*/@Testpublic void processCancelTest() {// 1 构建参数ApiEntity<ProcessCancelDto> dto = new ApiEntity<>();dto.setAppId("应用的ID");dto.setTimestamp(LocalDateTimeUtil.now());// 2  构建请求数据ProcessCancelDto processCancelDto = new ProcessCancelDto();processCancelDto.setUserAccount("账号");processCancelDto.setId("617501");processCancelDto.setReason("取消的原因");// 3 配置json序列化:指定日期格式JSONConfig jsonConfig = new JSONConfig();jsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss");// 4 设置数据dto.setData(processCancelDto);// 5 根据Data 生成Hash      HMac hMac = DigestUtil.hmac(HmacAlgorithm.HmacSHA512, "约定的签名秘钥".getBytes(StandardCharsets.UTF_8));dto.setSign(hMac.digestHex(JSONUtil.toJsonStr(dto.getData(), jsonConfig)));// 6 打印接口请求的数据System.out.println(JSONUtil.toJsonStr(dto, jsonConfig));}
}

测试数据的构建
在这里插入图片描述

三:测试接口

这里用apipost 测试结果
在这里插入图片描述

http://www.dtcms.com/a/299956.html

相关文章:

  • 深入解析YARN中的FairScheduler与CapacityScheduler:资源分配策略的核心区别
  • Aerospike Java客户端进阶:对象映射与Spring Data集成实战
  • spring Could 高频面试题
  • 【科普】java和html和lvgl生成页面有什么区别,还有什么方法可以生成?
  • 数据库HB OB mysql ck startrocks, ES存储特点,以及应用场景
  • 通过服务启动应用的流程(类似SystemUi启动流程)
  • Linux笔记5——常用命令-4
  • 深入浅出学习 KNN 算法:从原理到数字识别实践
  • 【Linux庖丁解牛】— 日志进程池 !
  • 大模型系列——Dify:知识库与外部知识库
  • SSH连接失败排查与解决教程: Connection refused
  • PromQL完全指南:掌握Prometheus核心查询语言
  • Ubuntu 22.04 配置 Zsh + Oh My Zsh + Powerlevel10k
  • 二十八、【Linux系统域名解析】DNS安装、子域授权、缓存DNS、分离解析、多域名解析
  • C++___快速入门(上)
  • 人工智能之数学基础:概率论之韦恩图的应用
  • WebAPIs里的filter
  • Android 编码规范全指南
  • 驱动-设备树-基本语法
  • Python爬虫实战:诗词名句网《三国演义》全集
  • 服务器:数字世界的隐形引擎
  • 《基于雅可比矢量近似的EIT触觉传感灵敏度非均匀校正》论文解读
  • ESP32实战:5分钟实现PC远程控制LED灯
  • C++类和对象(三)
  • IC测试之pogo pin学习与总结-20250726
  • 进制定义与转换详解
  • 1.Java发展简史与设计哲学
  • 最优估计准则与方法(5)加权最小二乘估计(WLS)_学习笔记
  • 360° 外壁镜头:小物体环外侧检测的创新突破
  • Python day25