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

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定制化的局域网会议软件,提供安全稳定的会议体验

在现代商业环境中&#xff0c;迅速而高效的沟通是企业成功的关键要素之一。而在传统的会议模式下&#xff0c;时间成本和地理限制往往给企业带来不小的困扰。针对这一问题&#xff0c;WorkPlus推出了一款创新的局域网会议软件——WorkPlus Meet&#xff0c;旨在为企业创造高效的…...

干货|小白也能自制电子相册赶紧码住~

你是否想拥有一个独一无二的电子相册&#xff0c;却又苦于不知道如何下手&#xff1f;今天教你一个简单的方法&#xff0c;即使你是小白&#xff0c;也能轻松自制电子相册&#xff01; 一、选择合适的工具 首先&#xff0c;你需要选择一个合适的工具来制作电子相册。有很多工具…...

docker之Harbor私有仓库

目录 一、什么是Harbor 二、Harbor的特性 三、Harbor的构成 1、六个组件 2、七个容器 四、私有镜像仓库的上传与下载 五、部署docker-compose服务 把项目中的镜像数据进行打包持久数据&#xff0c;如镜像&#xff0c;数据库等在宿主机的/data/目录下&#xff0c; 一、什么…...

服务器上部署python脚本

1.查看服务器上的python是否自带&#xff0c;一般都自带 2.将本地脚本上传到服务器 3.直接运行一下脚本看报什么错误 代码错误&#xff0c; 将f删除后报别的错误 上面是未安装依赖的错误。我们安装一下依赖 下面是编码的解决 #!/usr/bin/python # -*- coding: utf-8 -*- 先把…...

【excel技巧】如何在Excel表格中添加选项按钮?

不知道大家是否会9遇到需要勾中选项的情况&#xff0c;我们可以在电子表格中制作出可以勾选、选中的选项按钮&#xff0c;今天我们一起学习一下设置方法。 首先&#xff0c;我们需要先在excel工具栏中添加一个功能模块&#xff1a;开发工具 依次点击excel中的文件 – 选项 –…...

前端 vite+vue3——写一个随机抽奖组件

文章目录 ⭐前言⭐设计布局⭐交互设计⭐整体代码⭐insicode代码 ⭐总结⭐结束 ⭐前言 大家好&#xff0c;我是yma16&#xff0c;本文分享关于前端 vitevue3——写一个抽奖随机组件。 vue3系列相关文章&#xff1a; 前端vue2、vue3去掉url路由“ # ”号——nginx配置 csdn新星计…...

语音芯片基础知识 什么是语音芯 他有什么作用 发展趋势是什么

目录 一、语音芯片的简介 常见的语音芯片有哪些&#xff1f; 语音芯片的种类有很多&#xff0c;大体区分下来也就4个类别而已&#xff1a; 选型的经验说明如下&#xff1a; 推荐使用flash型语音芯片 一、语音芯片的简介 语音芯片基础知识&#xff1a; 什么是语音芯片&…...

设计模式01———简单工厂模式 c#

首先我们打开一个项目 在这个初始界面我们需要做一些准备工作 建基础通用包 创建一个Plane 重置后 缩放100倍 加一个颜色 任务&#xff1a;使用【简单工厂模式】生成四种不同怪物 【按不同路径移动】 首先资源商店下载四个怪物模型 接下来我们选取四个怪物作为预制体并分别起名…...

如何解决MidJourney错过付费后被暂停

问题 假定你已经成功订阅购买了 MidJourney 一段时间&#xff0c;下个月扣费周期到了。 如果你卡里余额不足&#xff0c;卡被封或失效了&#xff0c;或者你想着最近没啥用得上 MidJourney 的地方先省着不续费&#xff0c;等要用的时候就用不了。 如果想要去官网的续费页&…...

考研人考研魂——英语单词篇(20231010)

下一站&#xff0c;上岸 transplanttransportstorestoragestockstridestrikestringstructurestrikingstunprimaryprimeprimitiveprincipalpsychiatryprinciplepsychologyliableliberal transplant n. &#xff08;器官等的&#xff09;移植&#xff1b;移植的器官 vt. 移植&a…...

java 版 项目管理工程系统,实现项目全周期管理-源码交付

工程项目管理软件&#xff08;工程项目管理系统&#xff09;对建设工程项目管理组织建设、项目策划决策、规划设计、施工建设到竣工交付、总结评估、运维运营&#xff0c;全过程、全方位的对项目进行综合管理 工程项目各模块及其功能点清单 一、系统管理 1、数据字典&am…...

TOGAF(企业架构)

TOGAF 核心概念&#xff08;官方原版&#xff09; 什么是TOGAF&#xff1f; TOGAF?是一种经验证的企业架构方法和框架&#xff0c;被世界领先的组织用于提高业务效率。它是一个企业架构标准&#xff0c;确保企业架构专业人员之间的标准、方法和通信一致&#xff0c;以便我们…...

vue中v-model的原理是什么?v-model作用在组件上的原理是什么?sync修饰符的原理是什么?

vue中v-model的原理是什么&#xff1f; 特点&#xff1a;双向绑定 数据>视图 视图>数据 场景&#xff1a; 收集表单数据组件上 原理&#xff1a; v-model只是个语法题&#xff0c;本质是&#xff1a;v-model v-bind (:value) v-on (input) <template><…...

新闻api接口,新闻资讯,社交媒体,体育赛事,全国热门带正文新闻查询API接口

一、接口介绍 解决同一类新闻在不同平台上的内容获取问题&#xff0c;在归档主流新闻平台的内容数据基础上&#xff0c;对外提供统一的调用方式来完成实时、最新的相关新闻的获取&#xff0c;极大方便各类企业在自有软件中集成新闻内容的功能。支持200余个新闻大站&#xff0c;…...

Redis - php通过ssh方式连接到redis服务器

1.应用场景 主要用于使用php通过ssh方式连接到redis服务器&#xff0c;进行一些操作. 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工程 创建之后&#xff0c;src下是空的。可以在src下创建软件包Package&#xff0c;命名采用域名倒序。在软件包下再创建Java类。Java类运行后出现中文乱码&#xff0c;就到控制台和文件编码这两个地方设置编码。 2. 创建JavaWeb工程 2.1 在win11和IDEA中配置Tomca…...

Mac上brew切换国内源【极简方案】

前言 下载一些开源包如telnet时&#xff0c;通过brew下载经常由于网络不通&#xff0c;导致下载失败。所以mac用户最好一次性设置brew为国内源。 方案 极简四步&#xff0c;换Homebrew的镜像源为阿里云镜像&#xff0c;依次在终端执行以下几步&#xff1a; 1、cd “$(brew …...

计算机网络面试常问问题--保研及考研复试

前言&#xff1a; Hello大家好&#xff0c;我是Dream。今年保研上岸山东大学人工智能专业 &#xff08;经验贴&#xff09;&#xff0c;现在将我自己的专业课备考知识点整理出来&#xff0c;分享给大家&#xff0c;希望可以帮助到大家&#xff01;这是重点知识总结&#xff0c;…...

elasticsearch 8.5.3问题记录

一&#xff1a;解决 elasticsearch 高版本 warning: ignoring JAVA_HOMEC:\Program Files\Java\jdk-11&#xff1b; using bundled JDK if defined JAVA_HOME (set JAVA_HOME%JAVA_HOME%; )示例版本Elasticsearch 8.5.3 可以与 JDK 11 兼容&#xff0c;但不支持 JDK 17。确保选…...

多模态2025:技术路线“神仙打架”,视频生成冲上云霄

文&#xff5c;魏琳华 编&#xff5c;王一粟 一场大会&#xff0c;聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中&#xff0c;汇集了学界、创业公司和大厂等三方的热门选手&#xff0c;关于多模态的集中讨论达到了前所未有的热度。其中&#xff0c;…...

Spark 之 入门讲解详细版(1)

1、简介 1.1 Spark简介 Spark是加州大学伯克利分校AMP实验室&#xff08;Algorithms, Machines, and People Lab&#xff09;开发通用内存并行计算框架。Spark在2013年6月进入Apache成为孵化项目&#xff0c;8个月后成为Apache顶级项目&#xff0c;速度之快足见过人之处&…...

微软PowerBI考试 PL300-选择 Power BI 模型框架【附练习数据】

微软PowerBI考试 PL300-选择 Power BI 模型框架 20 多年来&#xff0c;Microsoft 持续对企业商业智能 (BI) 进行大量投资。 Azure Analysis Services (AAS) 和 SQL Server Analysis Services (SSAS) 基于无数企业使用的成熟的 BI 数据建模技术。 同样的技术也是 Power BI 数据…...

uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖

在前面的练习中&#xff0c;每个页面需要使用ref&#xff0c;onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入&#xff0c;需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

实现弹窗随键盘上移居中

实现弹窗随键盘上移的核心思路 在Android中&#xff0c;可以通过监听键盘的显示和隐藏事件&#xff0c;动态调整弹窗的位置。关键点在于获取键盘高度&#xff0c;并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...

Java面试专项一-准备篇

一、企业简历筛选规则 一般企业的简历筛选流程&#xff1a;首先由HR先筛选一部分简历后&#xff0c;在将简历给到对应的项目负责人后再进行下一步的操作。 HR如何筛选简历 例如&#xff1a;Boss直聘&#xff08;招聘方平台&#xff09; 直接按照条件进行筛选 例如&#xff1a…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

在鸿蒙HarmonyOS 5中使用DevEco Studio实现企业微信功能

1. 开发环境准备 ​​安装DevEco Studio 3.1​​&#xff1a; 从华为开发者官网下载最新版DevEco Studio安装HarmonyOS 5.0 SDK ​​项目配置​​&#xff1a; // module.json5 {"module": {"requestPermissions": [{"name": "ohos.permis…...

【SpringBoot自动化部署】

SpringBoot自动化部署方法 使用Jenkins进行持续集成与部署 Jenkins是最常用的自动化部署工具之一&#xff0c;能够实现代码拉取、构建、测试和部署的全流程自动化。 配置Jenkins任务时&#xff0c;需要添加Git仓库地址和凭证&#xff0c;设置构建触发器&#xff08;如GitHub…...

tauri项目,如何在rust端读取电脑环境变量

如果想在前端通过调用来获取环境变量的值&#xff0c;可以通过标准的依赖&#xff1a; std::env::var(name).ok() 想在前端通过调用来获取&#xff0c;可以写一个command函数&#xff1a; #[tauri::command] pub fn get_env_var(name: String) -> Result<String, Stri…...