gateway接口参数加解密
上篇介绍了多种加解密的使用java加密使用
本篇主要介绍在gateway网关中使用对参数解密和返回数据进行加密的操作
原理
下面使用的是AES加密 SHA1withRSA加签
1-用户使用拿到的AES秘钥和RSA私钥。对数据进行加密和加签
2-进行验签和时间的检验
3-将解密的数据返回到具体的调用方(通过特定的filter具体业务方是无感知加解密的)
4-将业务方数据加密返回给调用方
参数校验
@Slf4j
@Order(Ordered.HIGHEST_PRECEDENCE + 10)
@Component
public class SignatureValidationGatewayFilterFactory extends AbstractGatewayFilterFactory {private final EtrGatewayProperties etrGatewayProperties;@Autowiredpublic SignatureValidationGatewayFilterFactory(EtrGatewayProperties etrGatewayProperties) {this.etrGatewayProperties = etrGatewayProperties;}@Overridepublic GatewayFilter apply(Object config) {return (exchange, chain) -> {if (HttpMethod.GET.matches(exchange.getRequest().getMethodValue())|| HttpMethod.POST.matches(exchange.getRequest().getMethodValue())) {ModifyRequestBodyGatewayFilterFactory.Config modifyRequestConfig = new ModifyRequestBodyGatewayFilterFactory.Config().setContentType(ContentType.APPLICATION_JSON.getMimeType()).setRewriteFunction(String.class, String.class, (exchange1, originalRequestBody) -> {try {JSONObject jsonObject = JSONUtil.parseObj(originalRequestBody);String appId = jsonObject.getStr(SignatureConstants.SIGN_APPID);String sign = jsonObject.getStr(SignatureConstants.SIGN_KEY);String signType = jsonObject.getStr(SignatureConstants.SIGN_TYPE);String timeStamp = jsonObject.getStr(SignatureConstants.SIGN_TIME_STAMP);EtrGatewayProperties.SinatureConfig first = etrGatewayProperties.getSignatures().stream().filter(appConfig -> appConfig.getAppId().equalsIgnoreCase(appId)).findFirst().orElse(null);if (Objects.isNull(first)) {log.error("appId:{}不合法", appId);return Mono.error(BizException.of(GatewayErrorCodeEnum.SIGNATURE_ERROR));}if (StrUtil.isBlank(sign) || StrUtil.isBlank(signType) || !StrUtil.isNumeric(timeStamp)) {log.error("参数不合法:sign:{},signType:{},timestamp:{}", sign, signType, timeStamp);return Mono.error(BizException.of(GatewayErrorCodeEnum.SIGNATURE_ERROR));}// 验证时间戳if (!validateTimestamp(timeStamp, first)) {log.warn("Invalid timestamp for appId: {}", appId);return Mono.error(BizException.of(GatewayErrorCodeEnum.SIGNATURE_ERROR));}// 验证签名if (!validateSignature(jsonObject, appId, signType, sign, first)) {log.warn("Signature verification failed for appId: {}", appId);return Mono.error(BizException.of(GatewayErrorCodeEnum.SIGNATURE_ERROR));}String dataStr = decryptData(jsonObject.getStr(SignatureConstants.SIGN_DATA), first.getAesKey());if (StringUtils.isBlank(dataStr)) {return Mono.error(BizException.of(GatewayErrorCodeEnum.SIGNATURE_ERROR));}exchange1.getRequest().mutate().header(SignatureConstants.SIGN_APPID, appId);return Mono.just(dataStr);} catch (Exception e) {return Mono.error(e);}});return new ModifyRequestBodyGatewayFilterFactory().apply(modifyRequestConfig).filter(exchange, chain).onErrorResume(e -> handleFilterError(exchange, e));}return chain.filter(exchange);};}private boolean validateTimestamp(String timeStamp, EtrGatewayProperties.SinatureConfig appConfig) {Integer timestampExpire = Optional.ofNullable(appConfig.getTimeStampExpire()).orElse(300);DateTime time = DateUtil.parse(timeStamp, DateUtil.newSimpleFormat("yyyyMMddHHmmss"));long between = DateUtil.between(time, new Date(), DateUnit.SECOND);return Math.abs(between) <= timestampExpire;}private boolean validateSignature(JSONObject jsonObject, String appId, String signType, String sign, EtrGatewayProperties.SinatureConfig appConfig) {String publicKey = appConfig.getPublicKey();SignStrategy signStrategy = new DefaultSignStrategy();try {return signStrategy.verifyPost(jsonObject.getStr(SignatureConstants.SIGN_DATA), publicKey,CipherType.valueOf(signType.toUpperCase()), sign);} catch (Exception e) {log.error("Signature verification failed for appId: {}", appId, e);return false;}}private String decryptData(String data, String aesKey) {AES aes = SecureUtil.aes(aesKey.getBytes());return aes.decryptStr(data);}private Mono<Void> handleFilterError(ServerWebExchange exchange, Throwable e) {if (e instanceof BizException) {log.error("Filter error: {}", e.getMessage());return signatureError(exchange);}return Mono.error(e);}private Mono<Void> signatureError(ServerWebExchange exchange) {log.warn("Signature error: {}", exchange.getRequest().getURI().getPath());ApiResult<Object> result = ApiResult.fail(GatewayErrorCodeEnum.SIGNATURE_ERROR);ServerHttpResponse response = exchange.getResponse();response.setStatusCode(HttpStatus.UNAUTHORIZED);response.getHeaders().setContentType(MediaType.APPLICATION_JSON);DataBuffer buffer = response.bufferFactory().wrap(JSONUtil.toJsonStr(result).getBytes());return response.writeWith(Mono.just(buffer)).then(Mono.defer(response::setComplete));}
}
返回参数加密
@Order(Ordered.HIGHEST_PRECEDENCE + 20)
@Component
public class SignatureResGatewayFilterFactory extends ModifyResponseBodyGatewayFilterFactory {private final EtrGatewayProperties etrGatewayProperties;public SignatureResGatewayFilterFactory(ServerCodecConfigurer codecConfigurer, Set<MessageBodyDecoder> bodyDecoders,Set<MessageBodyEncoder> bodyEncoders, EtrGatewayProperties etrGatewayProperties) {super(codecConfigurer.getReaders(), bodyDecoders, bodyEncoders);this.etrGatewayProperties = etrGatewayProperties;}@Overridepublic GatewayFilter apply(Config config) {config.setRewriteFunction(String.class, String.class, (serverWebExchange, s) -> {JSONObject resJson = JSONUtil.parseObj(s);Integer code = resJson.getInt("code");if (200 == code) {String dataStr = resJson.getStr("data");if (StrUtil.isNotBlank(dataStr)) {String appId = serverWebExchange.getRequest().getHeaders().getFirst(SignatureConstants.SIGN_APPID);if (StrUtil.isBlank(appId)) {return Mono.error(BizException.of(GatewayErrorCodeEnum.SIGNATURE_ERROR));}AES aes = SecureUtil.aes(getAesKey(appId).getBytes());resJson.set("data", aes.encryptBase64(dataStr));return Mono.just(resJson.toString());}}return Mono.just(s);});ModifyResponseGatewayFilter gatewayFilter = new ModifyResponseGatewayFilter(config);gatewayFilter.setFactory(this);return gatewayFilter;}private String getAesKey(String appId) {EtrGatewayProperties.SinatureConfig first = etrGatewayProperties.getSignatures().stream().filter(appConfig -> appConfig.getAppId().equalsIgnoreCase(appId)).findFirst().orElse(null);if (Objects.isNull(first)) {throw BizException.of(GatewayErrorCodeEnum.SIGNATURE_ERROR);}String aesKey = first.getAesKey();if (StrUtil.isBlank(aesKey)) {throw BizException.of(GatewayErrorCodeEnum.SIGNATURE_ERROR);}return aesKey;}
}相关文章:
gateway接口参数加解密
上篇介绍了多种加解密的使用java加密使用 本篇主要介绍在gateway网关中使用对参数解密和返回数据进行加密的操作 原理 下面使用的是AES加密 SHA1withRSA加签 1-用户使用拿到的AES秘钥和RSA私钥。对数据进行加密和加签 2-进行验签和时间的检验 3-将解密的数据返回到具体的调用…...
WorkPlus定制化的局域网会议软件,提供安全稳定的会议体验
在现代商业环境中,迅速而高效的沟通是企业成功的关键要素之一。而在传统的会议模式下,时间成本和地理限制往往给企业带来不小的困扰。针对这一问题,WorkPlus推出了一款创新的局域网会议软件——WorkPlus Meet,旨在为企业创造高效的…...
干货|小白也能自制电子相册赶紧码住~
你是否想拥有一个独一无二的电子相册,却又苦于不知道如何下手?今天教你一个简单的方法,即使你是小白,也能轻松自制电子相册! 一、选择合适的工具 首先,你需要选择一个合适的工具来制作电子相册。有很多工具…...
docker之Harbor私有仓库
目录 一、什么是Harbor 二、Harbor的特性 三、Harbor的构成 1、六个组件 2、七个容器 四、私有镜像仓库的上传与下载 五、部署docker-compose服务 把项目中的镜像数据进行打包持久数据,如镜像,数据库等在宿主机的/data/目录下, 一、什么…...
服务器上部署python脚本
1.查看服务器上的python是否自带,一般都自带 2.将本地脚本上传到服务器 3.直接运行一下脚本看报什么错误 代码错误, 将f删除后报别的错误 上面是未安装依赖的错误。我们安装一下依赖 下面是编码的解决 #!/usr/bin/python # -*- coding: utf-8 -*- 先把…...
【excel技巧】如何在Excel表格中添加选项按钮?
不知道大家是否会9遇到需要勾中选项的情况,我们可以在电子表格中制作出可以勾选、选中的选项按钮,今天我们一起学习一下设置方法。 首先,我们需要先在excel工具栏中添加一个功能模块:开发工具 依次点击excel中的文件 – 选项 –…...
前端 vite+vue3——写一个随机抽奖组件
文章目录 ⭐前言⭐设计布局⭐交互设计⭐整体代码⭐insicode代码 ⭐总结⭐结束 ⭐前言 大家好,我是yma16,本文分享关于前端 vitevue3——写一个抽奖随机组件。 vue3系列相关文章: 前端vue2、vue3去掉url路由“ # ”号——nginx配置 csdn新星计…...
语音芯片基础知识 什么是语音芯 他有什么作用 发展趋势是什么
目录 一、语音芯片的简介 常见的语音芯片有哪些? 语音芯片的种类有很多,大体区分下来也就4个类别而已: 选型的经验说明如下: 推荐使用flash型语音芯片 一、语音芯片的简介 语音芯片基础知识: 什么是语音芯片&…...
设计模式01———简单工厂模式 c#
首先我们打开一个项目 在这个初始界面我们需要做一些准备工作 建基础通用包 创建一个Plane 重置后 缩放100倍 加一个颜色 任务:使用【简单工厂模式】生成四种不同怪物 【按不同路径移动】 首先资源商店下载四个怪物模型 接下来我们选取四个怪物作为预制体并分别起名…...
如何解决MidJourney错过付费后被暂停
问题 假定你已经成功订阅购买了 MidJourney 一段时间,下个月扣费周期到了。 如果你卡里余额不足,卡被封或失效了,或者你想着最近没啥用得上 MidJourney 的地方先省着不续费,等要用的时候就用不了。 如果想要去官网的续费页&…...
考研人考研魂——英语单词篇(20231010)
下一站,上岸 transplanttransportstorestoragestockstridestrikestringstructurestrikingstunprimaryprimeprimitiveprincipalpsychiatryprinciplepsychologyliableliberal transplant n. (器官等的)移植;移植的器官 vt. 移植&a…...
java 版 项目管理工程系统,实现项目全周期管理-源码交付
工程项目管理软件(工程项目管理系统)对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营,全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&am…...
TOGAF(企业架构)
TOGAF 核心概念(官方原版) 什么是TOGAF? TOGAF?是一种经验证的企业架构方法和框架,被世界领先的组织用于提高业务效率。它是一个企业架构标准,确保企业架构专业人员之间的标准、方法和通信一致,以便我们…...
vue中v-model的原理是什么?v-model作用在组件上的原理是什么?sync修饰符的原理是什么?
vue中v-model的原理是什么? 特点:双向绑定 数据>视图 视图>数据 场景: 收集表单数据组件上 原理: v-model只是个语法题,本质是:v-model v-bind (:value) v-on (input) <template><…...
新闻api接口,新闻资讯,社交媒体,体育赛事,全国热门带正文新闻查询API接口
一、接口介绍 解决同一类新闻在不同平台上的内容获取问题,在归档主流新闻平台的内容数据基础上,对外提供统一的调用方式来完成实时、最新的相关新闻的获取,极大方便各类企业在自有软件中集成新闻内容的功能。支持200余个新闻大站,…...
Redis - php通过ssh方式连接到redis服务器
1.应用场景 主要用于使用php通过ssh方式连接到redis服务器,进行一些操作. 2.学习/操作 1.文档阅读 chatgpt & 其他资料 SSH - 学习与实践探究_ssh应用场景 2.整理输出 2.1 是什么 TBD 2.2 为什么需要「应用场景」 TBD 2.3 什么时候出现「历史发展」 TBD 2.4 …...
IDEA的使用(四)创建不同类型的工程(IntelliJ IDEA 2022.1.3版本)
1. 创建Java工程 创建之后,src下是空的。可以在src下创建软件包Package,命名采用域名倒序。在软件包下再创建Java类。Java类运行后出现中文乱码,就到控制台和文件编码这两个地方设置编码。 2. 创建JavaWeb工程 2.1 在win11和IDEA中配置Tomca…...
Mac上brew切换国内源【极简方案】
前言 下载一些开源包如telnet时,通过brew下载经常由于网络不通,导致下载失败。所以mac用户最好一次性设置brew为国内源。 方案 极简四步,换Homebrew的镜像源为阿里云镜像,依次在终端执行以下几步: 1、cd “$(brew …...
计算机网络面试常问问题--保研及考研复试
前言: Hello大家好,我是Dream。今年保研上岸山东大学人工智能专业 (经验贴),现在将我自己的专业课备考知识点整理出来,分享给大家,希望可以帮助到大家!这是重点知识总结,…...
elasticsearch 8.5.3问题记录
一:解决 elasticsearch 高版本 warning: ignoring JAVA_HOMEC:\Program Files\Java\jdk-11; using bundled JDK if defined JAVA_HOME (set JAVA_HOME%JAVA_HOME%; )示例版本Elasticsearch 8.5.3 可以与 JDK 11 兼容,但不支持 JDK 17。确保选…...
C++11避坑指南:auto类型推导的7个常见错误及如何避免
C11避坑指南:auto类型推导的7个常见错误及如何避免 在C11标准中,auto关键字的引入极大地简化了代码编写过程,让开发者从繁琐的类型声明中解放出来。然而,这种便利性也带来了新的陷阱——类型推导的隐式规则可能导致意料之外的行为…...
Harbor集成Trivy实现镜像安全扫描:从安装到离线环境配置全攻略
1. 为什么需要镜像安全扫描? 最近在帮客户部署容器平台时遇到一个典型问题:测试环境频繁出现应用崩溃,排查后发现是基础镜像中的某个高危漏洞导致的。这让我意识到,镜像安全扫描不是可选项,而是现代DevOps流程中的必选…...
2025届最火的AI写作平台实际效果
Ai论文网站排名(开题报告、文献综述、降aigc率、降重综合对比) TOP1. 千笔AI TOP2. aipasspaper TOP3. 清北论文 TOP4. 豆包 TOP5. kimi TOP6. deepseek 当今,人工智能技术迅猛发展,在此情形下,AI论文网站已然成…...
Analog入门指南:如何在5分钟内搭建你的第一个Angular全栈应用
Analog入门指南:如何在5分钟内搭建你的第一个Angular全栈应用 【免费下载链接】analog The fullstack meta-framework for Angular. Powered by Vite and Nitro 项目地址: https://gitcode.com/gh_mirrors/an/analog Analog是一个功能强大的Angular全栈元框架…...
Ubuntu上彻底卸载Ollama的保姆级命令指南(附残留文件清理)
Ubuntu上彻底卸载Ollama的深度清理指南:从基础命令到系统级排查 在AI工具快速迭代的今天,许多开发者都会在本地环境测试各种大模型框架。Ollama作为轻量级的大模型运行工具,虽然安装便捷,但当需要彻底移除时,简单的删除…...
保姆级教程:用C# WinForm给STM32写个Modbus固件升级工具(附完整源码)
从零构建STM32固件升级工具:C# WinForm与Modbus协议深度实践 1. 开发环境与项目初始化 在Visual Studio 2022中新建Windows窗体应用项目时,建议选择.NET Framework 4.7.2或更高版本以获得最佳兼容性。项目创建后,首先需要配置NuGet包管理器安…...
Wand-Enhancer技术解析与选型指南:解锁WeMod高级功能的完整路径
Wand-Enhancer技术解析与选型指南:解锁WeMod高级功能的完整路径 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/gh_mirrors/we/Wand-Enhancer Wand-Enhancer是一款针对WeM…...
用鲸鱼优化算法(WOA)整定PID参数:Matlab与Simulink实战
鲸鱼优化算法(WOA)整定 PID 参数,m 文件加 simulink仿真,仿真程序给出适应度优化曲线,参数优化曲线以及优化对比波形,适用 matlab 2021b 及以上版本在自动控制领域,PID控制器因其结构简单、稳定…...
Realistic Vision V5.1虚拟摄影棚快速上手:新手3步生成比肩单反的人像
Realistic Vision V5.1虚拟摄影棚快速上手:新手3步生成比肩单反的人像 1. 为什么选择Realistic Vision V5.1虚拟摄影棚 如果你一直想尝试专业级人像摄影,但又苦于没有昂贵的单反设备和摄影棚,Realistic Vision V5.1虚拟摄影棚就是为你量身定…...
4个维度解析YetAnotherKeyDisplayer:开源实时按键可视化工具全指南
4个维度解析YetAnotherKeyDisplayer:开源实时按键可视化工具全指南 【免费下载链接】YetAnotherKeyDisplayer The application for displaying pressed keys of the keyboard 项目地址: https://gitcode.com/gh_mirrors/ye/YetAnotherKeyDisplayer YetAnothe…...
