SpringBoot实现自定义environment中的value加密
environment中的value为什么要加密?
未经过加密的配置文件,密码均是采用明文密码,很容易导致信息泄露。
SpringBoot environment中的value加密代码如下
package com.xxx.core.encryption;import com.google.common.collect.Maps;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.boot.env.OriginTrackedMapPropertySource;
import org.springframework.boot.origin.OriginTrackedValue;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.MutablePropertySources;
import org.springframework.core.env.PropertySource;import java.util.Map;/*** @author HanKeQi* @date 2023/9/4*/
@Slf4j
public class EnableEncryptionData implements BeanFactoryPostProcessor, Ordered {private final ConfigurableEnvironment environment;//根据自己需求自定义private static final String PREFIX = "ENC(";private static final String SUFFIX = ")";/*** 扫描自定义配置的文件*/private static final String BOOTSTRAP_CONFIGURE = "bootstrap";public EnableEncryptionData(ConfigurableEnvironment environment) {this.environment = environment;}@Overridepublic void postProcessBeanFactory(ConfigurableListableBeanFactory configurableListableBeanFactory) throws BeansException {MutablePropertySources propertySources = environment.getPropertySources();for (PropertySource<?> propertySource: propertySources){if (propertySource instanceof OriginTrackedMapPropertySource){OriginTrackedMapPropertySource originTrackedMapPropertySource = (OriginTrackedMapPropertySource) propertySource;String activeName = originTrackedMapPropertySource.getName();Map<String, Object> activeSource = (Map<String, Object>)propertySources.get(activeName).getSource();Map<String, Object> newConfigMap = Maps.newHashMap();activeSource.forEach((k,v)->{if (v instanceof OriginTrackedValue){Object valueObj = ((OriginTrackedValue) v).getValue();if (valueObj instanceof String){String valueEncryptionStr = (String) valueObj;if (!StringUtils.isEmpty(valueEncryptionStr) && valueEncryptionStr.startsWith(PREFIX) && valueEncryptionStr.endsWith(SUFFIX)){try {valueEncryptionStr = getEncryptionStr(valueEncryptionStr);valueEncryptionStr = AesUtils.decodeStr(valueEncryptionStr, AesUtils.P_KEY);newConfigMap.put(k, valueEncryptionStr);return;}catch (Exception e){e.printStackTrace();}}}}newConfigMap.put(k, v);});propertySources.replace(activeName, new OriginTrackedMapPropertySource(activeName , newConfigMap, true));}}}@Overridepublic int getOrder() {return Ordered.LOWEST_PRECEDENCE - 100;}/*** 获取加密后的信息* @param encryptionStr* @return*/private static String getEncryptionStr(String encryptionStr){encryptionStr = encryptionStr.substring(PREFIX.length());encryptionStr = encryptionStr.substring(0, encryptionStr.length()-SUFFIX.length());return encryptionStr;}
}
springboot 配置Configuration
package com.xxx.core.encryption;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.ConfigurableEnvironment;/*** @author HanKeQi* @date 2022/10/30*/
@Configuration
public class EnvironmentConfig {@Beanpublic static EnableEncryptionData enableEncryptionData(final ConfigurableEnvironment environment) {return new EnableEncryptionData(environment);}
}
Aes加密代码
package com.xxx.util.encrypt;import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.util.Arrays;/*** @author HanKeQi* @date 2022/10/30*/
@Slf4j
public class AesUtils {public static final String IV = "vKapxbKpyptKkwuP";private static final String P_KCS5_PADDING="AES/CBC/PKCS5Padding";private static final String KEY = "AES";public static final String P_KEY = "6U7Si019ireqa7vAscWBkbPClOYtn6gb";/*** @param content base64处理过的字符串* @param pkey 密匙* @return String 返回类型* @throws Exception* @throws* @Title: aesDecodeStr* @Description: 解密 失败将返回NULL*/public static String decodeStr(String content, String pkey) throws Exception {try {log.info("待解密内容: {}", content);byte[] base64DecodeStr = Base64.decodeBase64(content);byte[] aesDecode = decode(base64DecodeStr, pkey);if (aesDecode == null) {return null;}String result;result = new String(aesDecode, "UTF-8");return result;} catch (Exception e) {throw new Exception("解密异常");}}/*** 解密 128位** @param content 解密前的byte数组* @param pkey 密匙* @return result 解密后的byte数组* @throws Exception*/public static byte[] decode(byte[] content, String pkey,String IV) throws Exception {SecretKeySpec skey = new SecretKeySpec(pkey.getBytes(), KEY);IvParameterSpec iv = new IvParameterSpec(IV.getBytes("UTF-8"));//创建密码器Cipher cipher = Cipher.getInstance(P_KCS5_PADDING);//初始化解密器cipher.init(Cipher.DECRYPT_MODE, skey, iv);byte[] result = cipher.doFinal(content);// 解密return result;}public static byte[] decode(byte[] content, String pkey) throws Exception {return decode(content,pkey,IV);}/*** @param content 加密前原内容* @param pkey 长度为16个字符,128位* @return base64EncodeStr aes加密完成后内容* @throws* @Title: aesEncryptStr* @Description: aes对称加密*/public static String encryptStr(String content, String pkey) {byte[] aesEncrypt = encrypt(content, pkey);String base64EncodeStr = Base64.encodeBase64String(aesEncrypt);return base64EncodeStr;}/*** 加密 128位** @param content 需要加密的原内容* @param pkey 密匙* @return*/public static byte[] encrypt(String content, String pkey, String iv) {try {//SecretKey secretKey = generateKey(pkey);//byte[] enCodeFormat = secretKey.getEncoded();SecretKeySpec skey = new SecretKeySpec(pkey.getBytes(), KEY);Cipher cipher = Cipher.getInstance(P_KCS5_PADDING);// "算法/加密/填充"IvParameterSpec ivParameterSpec = new IvParameterSpec(iv.getBytes());cipher.init(Cipher.ENCRYPT_MODE, skey, ivParameterSpec);//初始化加密器byte[] encrypted = cipher.doFinal(content.getBytes("UTF-8"));return encrypted; // 加密} catch (Exception e) {log.info("encrypt() method error:", e);}return null;}public static byte[] encrypt(String content, String pkey) {return encrypt(content,pkey, IV);}}
配置文件
spring:redis:database: 1host: redis.commons.svc.cluster.localport: 6379# 使用了 AesUtils.encryptStr("ADoZH2Gw6KEw51c3Mk", P_KEY);password: ENC(hji+7pHQpX0f0/dVncyT/leJ6sWHiCUlFq7LdDJjo1s=)
相关文章:
SpringBoot实现自定义environment中的value加密
environment中的value为什么要加密? 未经过加密的配置文件,密码均是采用明文密码,很容易导致信息泄露。 SpringBoot environment中的value加密代码如下 package com.xxx.core.encryption;import com.google.common.collect.Maps; import lomb…...
celery的用法--任务调度
在Celery中,任务(Task)是执行特定操作的基本单元。任务可以异步执行,可以带有参数,可以返回结果,可以链式调用,还可以设置任务优先级、超时等属性。 1.定义任务: 使用app.task装饰器…...
MyBatis-Plus学习笔记总结
一、查询 构造器分为QueryWrapper和LambdaQueryWrapper 创建实体类User package com.system.mybatisplus.model;import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.…...
How Language Model Hallucinations Can Snowball
本文是LLM系列文章,针对《How Language Model Hallucinations Can Snowball》的翻译。 语言模型幻觉是如何产生雪球的 摘要1 引言2 为什么我们期待幻觉像滚雪球一样越滚越大?3 实验4 我们能防止雪球幻觉吗?5 相关工作6 结论局限性 摘要 在实…...
autojs修改顶部标题栏颜色
顶部标题栏的名字是statusBarColor 不是toolbar。难怪我搜索半天搜不到 修改之后变成这样了 代码如下: "ui"; importClass(android.view.View); importClass(android.graphics.Color); ui.statusBarColor(Color.parseColor("#ffffff")); ui.…...
arppy gis 读取text 并批量添加字段 arcpy.AddField_management
arppy gis 读取text 并批量添加字段 arcpy.AddField_management 例:给“省级行政区域”添加“A、B、C、D” 4个字段。 (1)用Excel制作出字段及其描述表,定义字段结构; (2)复制除标题行以为的内…...
Pandas中at、iat函数详解
前言 嗨喽,大家好呀~这里是爱看美女的茜茜呐 at 函数:通过行名和列名来取值(取行名为a, 列名为A的值) iat 函数:通过行号和列号来取值(取第1行,第1列的值) 本文给出at、iat常见的…...
【Spring Boot】JPA — JPA入门
JPA简介 1. JPA是什么 JPA是Sun官方提出的Java持久化规范,它为Java开发人员提供了一种对象/关联映射工具来管理Java应用中的关系数据,通过注解或者XML描述“对象-关系表”之间的映射关系,并将实体对象持久化到数据库中,极大地简…...
c#反射(Reflection)
当我们在C#中使用反射时,可以动态地获取和操作程序集、类型和成员。下面是一个简单的C#反射示例,展示了如何使用反射来调用一个类的方法: using System; using System.Reflection;public class MyClass {public void MyMethod(){Console.Wri…...
Lua 元表和元方法
一、元表 元表可以修改一个值在面对一个未知操作时的行为,Lua 中使用 table 作为元表的承载。 元表只能给出预先定义的操作集合的行为,比类会更加受限制,不支持继承。 Lua 每一个值都可以有元表 : 表和用户数据类型都具有各自…...
【Git】01-Git基础
文章目录 Git基础1. 简述1.1 版本管理演变1.2 Git的特点 2. Git安装2.1 安装文档2.1 配置user信息 3. 创建仓库3.1 场景3.2 暂存区和工作区 4. 重命名5. 常用git log版本历史5.1 查看当前分支日志5.2 简洁查看日志5.3 查看最近指定条数的日志 6. 通过图形界面工具查看版本7. 探…...
【Vue2.0源码学习】生命周期篇-初始化阶段(initState)
文章目录 1. 前言2. initState函数分析3. 初始化props3.1 规范化数据3.2 initProps函数分析3.3 validateProp函数分析3.4 getPropDefaultValue函数分析3.5 assertProp函数分析 4. 初始化methods5. 初始化data6. 初始化computed6.1 回顾用法6.2 initComputed函数分析6.3 defineC…...
专升本英语零基础学习
1. 词法 1.1 名词 名词(n.),是词类的一种,属于实词。他表示人,物,事,地点或抽象概念的统一名称。 1.1 名词的含义 名词(n.),是词类的一种,属于实词。他表示人&#x…...
QUIC协议连接详解(二)
目录 一:RTT解释 二:QUIC 1-RTT连接 三:QUIC 0-RTT连接 一:RTT解释 在介绍QUIC协议的连接之前先科普一下什么是RTT。RTT是Round-Trip Time的英文缩写,翻译过来就是一趟来回的时间即往返时延。时间计算即从发送方发送…...
JAVA 经常遇到一些问题【第二部分36~51】
重拾者: 每日记录至目前(记录51种不同场景的问题可参考解决方案) 异常就两部分: 1、excepiton信息: 报错产生的原因 2、at开头表示: 异常产生的代码位置。 欢迎关注本人微信公众号:AIM…...
蓝桥杯打卡Day6
文章目录 N的阶乘基本算术整数查询 一、N的阶乘OI链接 本题思路:本题是关于高精度的模板题。 #pragma GCC optimize(3) #include <bits/stdc.h>constexpr int N1010;std::vector<int> a; std::vector<int> f[N];std::vector<int> mul(in…...
spark集群问题汇总
一、 磁盘问题 问题描述可能原因解决措施core节点磁盘不足, 并且持续增加未开启spark-history的日志清理打开日志清理: spark.history.fs.cleaner.enabled task节点磁盘不足 APP应用使用磁盘过大: 1. 严重的数据倾斜 2. 应用本身数据量大 1. 解决数据倾斜 2. 加大资源, 增加e…...
WebServer 解析HTTP 请求报文
一、TCP 状态转换 浏览器访问网址,TCP传输全过程 二、TCP协议的通信过程 三、TCP 通信流程 // TCP 通信的流程 // 服务器端 (被动接受连接的角色) 1. 创建一个用于监听的套接字- 监听:监听有客户端的连接- 套接字:这…...
Golang开发--interface的使用
在Go语言中,接口(interface)是一种特殊的类型,它定义了一组方法的集合。接口为实现多态性提供了一种机制,允许不同的数据类型实现相同的方法,从而可以以统一的方式处理这些不同类型的对象。接口在Go中广泛用…...
2023 年高教社杯全国大学生数学建模竞赛题目 B 题 多波束测线问题
B 题 多波束测线问题 单波束测深是利用声波在水中的传播特性来测量水体深度的技术。声波在均匀介质中作匀速直线传播,在不同界面上产生反射,利用这一原理,从测量船换能器垂直向海底发射声波信号,并记录从声波发射到信号接收的传播…...
浅谈 React Hooks
React Hooks 是 React 16.8 引入的一组 API,用于在函数组件中使用 state 和其他 React 特性(例如生命周期方法、context 等)。Hooks 通过简洁的函数接口,解决了状态与 UI 的高度解耦,通过函数式编程范式实现更灵活 Rea…...
多模态2025:技术路线“神仙打架”,视频生成冲上云霄
文|魏琳华 编|王一粟 一场大会,聚集了中国多模态大模型的“半壁江山”。 智源大会2025为期两天的论坛中,汇集了学界、创业公司和大厂等三方的热门选手,关于多模态的集中讨论达到了前所未有的热度。其中,…...
stm32G473的flash模式是单bank还是双bank?
今天突然有人stm32G473的flash模式是单bank还是双bank?由于时间太久,我真忘记了。搜搜发现,还真有人和我一样。见下面的链接:https://shequ.stmicroelectronics.cn/forum.php?modviewthread&tid644563 根据STM32G4系列参考手…...
TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案
一、TRS收益互换的本质与业务逻辑 (一)概念解析 TRS(Total Return Swap)收益互换是一种金融衍生工具,指交易双方约定在未来一定期限内,基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...
AI,如何重构理解、匹配与决策?
AI 时代,我们如何理解消费? 作者|王彬 封面|Unplash 人们通过信息理解世界。 曾几何时,PC 与移动互联网重塑了人们的购物路径:信息变得唾手可得,商品决策变得高度依赖内容。 但 AI 时代的来…...
安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
「全栈技术解析」推客小程序系统开发:从架构设计到裂变增长的完整解决方案
在移动互联网营销竞争白热化的当下,推客小程序系统凭借其裂变传播、精准营销等特性,成为企业抢占市场的利器。本文将深度解析推客小程序系统开发的核心技术与实现路径,助力开发者打造具有市场竞争力的营销工具。 一、系统核心功能架构&…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
