方法一:将私钥存入环境变量,环境变量指什么//spring中,rsa私钥应该怎么处置
环境变量(Environment Variables)是操作系统提供的一种机制,用于存储和传递配置信息或敏感数据(如密钥、密码等)。每个进程都可以访问一组环境变量,这些变量在操作系统级别定义,可以被应用程序读取和使用。
在 Spring 应用中,将私钥存入环境变量是一种常见的做法,可以避免将敏感信息硬编码在代码或配置文件中,从而提高安全性。
1. 什么是环境变量?
环境变量是操作系统级别的键值对(Key-Value),用于存储配置信息。例如:
JAVA_HOME:指向 Java 安装路径。PATH:定义可执行文件的搜索路径。RSA_PRIVATE_KEY:存储 RSA 私钥。
环境变量可以在以下场景中使用:
- 操作系统启动时加载。
- 应用程序运行时读取。
- 通过命令行或脚本设置。
2. 如何设置环境变量?
2.1 在 Linux/MacOS 中设置
-
临时设置(仅在当前终端会话有效):
export RSA_PRIVATE_KEY="MIIEvQIBADANBgkqhkiG9w0BAQEFAASC..." -
永久设置(对所有终端会话有效):
- 编辑
~/.bashrc或~/.zshrc文件:echo 'export RSA_PRIVATE_KEY="MIIEvQIBADANBgkqhkiG9w0BAQEFAASC..."' >> ~/.bashrc source ~/.bashrc
- 编辑
2.2 在 Windows 中设置
-
临时设置(仅在当前命令行窗口有效):
set RSA_PRIVATE_KEY=MIIEvQIBADANBgkqhkiG9w0BAQEFAASC... -
永久设置(对所有命令行窗口有效):
- 打开“系统属性” → “高级” → “环境变量”。
- 在“系统变量”或“用户变量”中添加
RSA_PRIVATE_KEY。
2.3 在 Docker 中设置
在 docker-compose.yml 或 Docker 命令中设置:
environment:- RSA_PRIVATE_KEY=MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...
3. 在 Spring 中读取环境变量
Spring 提供了多种方式读取环境变量,以下是常用方法:
3.1 使用 @Value 注解
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;@Component
public class RsaKeyConfig {@Value("${RSA_PRIVATE_KEY}") // 从环境变量注入private String privateKey;public String getPrivateKey() {return privateKey;}
}
3.2 使用 Environment 对象
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Component;@Component
public class RsaKeyConfig {private final Environment env;public RsaKeyConfig(Environment env) {this.env = env;}public String getPrivateKey() {return env.getProperty("RSA_PRIVATE_KEY");}
}
3.3 在 application.properties 中引用环境变量
# application.properties
rsa.private-key=${RSA_PRIVATE_KEY}
然后在代码中读取:
@Value("${rsa.private-key}")
private String privateKey;
4. 环境变量的安全性
优点
- 避免硬编码:私钥不直接写在代码中,降低泄露风险。
- 动态配置:不同环境(开发、测试、生产)可以使用不同的私钥。
- 集中管理:通过操作系统或容器平台统一管理环境变量。
缺点
- 访问控制:需确保只有授权用户和进程可以访问环境变量。
- 泄露风险:如果服务器被入侵,环境变量可能被窃取。
最佳实践
- 限制访问权限:
- 确保只有应用进程可以读取环境变量。
- 使用操作系统权限控制(如 Linux 的
chmod和chown)。
- 加密存储:
- 在容器平台(如 Kubernetes)中使用 Secrets 存储环境变量。
- 日志安全:
- 避免在日志中打印环境变量。
5. 完整代码示例
5.1 设置环境变量
# Linux/MacOS
export RSA_PRIVATE_KEY="MIIEvQIBADANBgkqhkiG9w0BAQEFAASC..."# Windows
set RSA_PRIVATE_KEY=MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...
5.2 Spring 代码
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import javax.annotation.PostConstruct;
import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.Base64;@Configuration
public class RsaKeyConfig {@Value("${RSA_PRIVATE_KEY}") // 从环境变量注入private String privateKeyStr;private PrivateKey privateKey;@PostConstructpublic void init() throws Exception {// 将 Base64 编码的私钥字符串转换为 PrivateKey 对象byte[] keyBytes = Base64.getDecoder().decode(privateKeyStr);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");this.privateKey = keyFactory.generatePrivate(keySpec);}public PrivateKey getPrivateKey() {return privateKey;}
}
5.3 使用私钥
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import javax.crypto.Cipher;@Service
public class AuthService {@Autowiredprivate RsaKeyConfig rsaKeyConfig;public String decrypt(String encryptedData) throws Exception {PrivateKey privateKey = rsaKeyConfig.getPrivateKey();Cipher cipher = Cipher.getInstance("RSA");cipher.init(Cipher.DECRYPT_MODE, privateKey);byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData));return new String(decryptedBytes);}
}
6. 总结
- 环境变量是操作系统级别的键值对,用于存储配置信息或敏感数据。
- 优点:避免硬编码,支持动态配置,集中管理。
- 最佳实践:限制访问权限,加密存储,避免日志泄露。
- 适用场景:开发、测试和生产环境均可使用,适合中小型项目或容器化部署。
- 、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、、
- 在 Spring 应用中,RSA 私钥的安全性至关重要。如果私钥泄露,攻击者可以解密敏感数据(如用户密码、加密的通信内容等),因此必须遵循严格的私钥管理规范。以下是完整的处理方案和代码实现:
一、私钥存储的常见错误
1. 硬编码在代码中
- 风险:代码提交到 Git 仓库后,私钥可能被泄露。
// ❌ 错误示例:私钥硬编码 String privateKey = "MIIEvQIBADANBgkqhkiGw...";
2. 明文存储在配置文件中
- 风险:配置文件可能被未授权访问。
# ❌ 错误示例:application.properties rsa.private-key=MIIEvQIBADANBgkqhkiGw...
3. 未加密的服务器本地存储
- 风险:服务器被入侵后,私钥可能被窃取。
二、安全的私钥管理方案
方案 1:通过环境变量注入
实现步骤
-
将私钥存入环境变量:
# Linux/MacOS export RSA_PRIVATE_KEY="MIIEvQIBADANBgkqhkiGw..."# Windows (PowerShell) $env:RSA_PRIVATE_KEY="MIIEvQIBADANBgkqhkiGw..." -
在 Spring 中读取环境变量:
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import javax.annotation.PostConstruct; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.spec.PKCS8EncodedKeySpec; import java.util.Base64;@Configuration public class RsaKeyConfig {@Value("${RSA_PRIVATE_KEY}") // 从环境变量注入private String privateKeyStr;private PrivateKey privateKey;@PostConstructpublic void init() throws Exception {// 将 Base64 编码的私钥字符串转换为 PrivateKey 对象byte[] keyBytes = Base64.getDecoder().decode(privateKeyStr);PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);KeyFactory keyFactory = KeyFactory.getInstance("RSA");this.privateKey = keyFactory.generatePrivate(keySpec);}public PrivateKey getPrivateKey() {return privateKey;} }
优点
- 私钥不写入代码或配置文件,依赖部署环境的安全性。
- 适合开发和生产环境。
缺点
- 需确保服务器环境变量不被未授权访问。
方案 2:加密配置文件(Jasypt)
实现步骤
-
添加 Jasypt 依赖:
<dependency><groupId>com.github.ulisesbocchio</groupId><artifactId>jasypt-spring-boot-starter</artifactId><version>3.0.5</version> </dependency> -
加密私钥:
# 使用 Jasypt 加密私钥 java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI \input="MIIEvQIBADANBgkqhkiGw..." \password=your-secret-key \algorithm=PBEWithMD5AndDES -
配置加密后的私钥:
# application.properties rsa.private-key=ENC(加密后的字符串) -
启动时提供解密密钥:
java -jar your-app.jar -Djasypt.encryptor.password=your-secret-key -
在代码中解密:
import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component;@Component public class RsaKeyConfig {@Value("${rsa.private-key}")private String encryptedPrivateKey;public PrivateKey getPrivateKey() {// 实际场景中,Jasypt 会自动解密配置项byte[] keyBytes = Base64.getDecoder().decode(encryptedPrivateKey);// 转换为 PrivateKey 对象(同方案1)} }
优点
- 配置文件中的私钥是加密的,即使泄露也无法直接使用。
- 适合需要版本控制配置文件的场景。
方案 3:密钥管理服务(KMS)
实现步骤(以 AWS KMS 为例)
-
将私钥存储在 AWS KMS:
- 通过 AWS 控制台或 SDK 创建一个加密密钥(CMK)。
-
在 Spring 中动态获取私钥:
import com.amazonaws.services.kms.AWSKMS; import com.amazonaws.services.kms.AWSKMSClientBuilder; import com.amazonaws.services.kms.model.DecryptRequest; import java.nio.ByteBuffer;@Component public class AwsKmsService {private final AWSKMS kmsClient = AWSKMSClientBuilder.defaultClient();public String decryptPrivateKey(byte[] encryptedKey) {DecryptRequest decryptRequest = new DecryptRequest().withCiphertextBlob(ByteBuffer.wrap(encryptedKey));ByteBuffer plaintext = kmsClient.decrypt(decryptRequest).getPlaintext();return new String(plaintext.array(), StandardCharsets.UTF_8);} } -
使用解密后的私钥:
@Service public class AuthService {@Autowiredprivate AwsKmsService kmsService;public PrivateKey loadPrivateKey() throws Exception {byte[] encryptedKey = // 从数据库或安全存储中加载加密的私钥String privateKeyStr = kmsService.decryptPrivateKey(encryptedKey);// 转换为 PrivateKey 对象(同方案1)} }
优点
- 私钥由 AWS 托管,支持自动轮换和访问控制。
- 适合云原生应用。
方案 4:硬件安全模块(HSM)
实现步骤
-
将私钥存储在 HSM:
- 使用 HSM 设备(如 SafeNet Luna)生成并存储密钥。
-
通过 HSM 接口访问私钥:
import java.security.KeyStore; import java.security.PrivateKey;public class HsmService {public PrivateKey getPrivateKey() throws Exception {KeyStore keyStore = KeyStore.getInstance("Luna");keyStore.load(null, null); // 使用 HSM 提供的凭据return (PrivateKey) keyStore.getKey("my-rsa-key", null);} }
优点
- 硬件级安全,私钥永不离开 HSM。
- 适合金融、政府等高安全场景。
三、最佳实践
- 最小化权限:
- 限制服务器和环境变量的访问权限,仅允许应用进程读取私钥。
- 密钥轮换:
- 定期更换密钥对(如每 3 个月一次),旧密钥仅用于解密历史数据。
- 审计与监控:
- 记录私钥的使用日志,监控异常访问行为。
- 代码审查:
- 使用 Git Hooks 或扫描工具(如 TruffleHog)防止私钥提交到仓库。
四、总结
- 推荐方案:
- 开发环境:环境变量或 Jasypt 加密配置文件。
- 生产环境:AWS KMS、HashiCorp Vault 或 HSM。
- 核心原则:
- 私钥不落地(不硬编码、不明文存储)。
- 依赖硬件或云服务提供商的密钥管理能力。
相关文章:
方法一:将私钥存入环境变量,环境变量指什么//spring中,rsa私钥应该怎么处置
环境变量(Environment Variables)是操作系统提供的一种机制,用于存储和传递配置信息或敏感数据(如密钥、密码等)。每个进程都可以访问一组环境变量,这些变量在操作系统级别定义,可以被应用程序读…...
React中useState()钩子和函数式组件底层渲染流程详解
useState()钩子底层渲染流程 React中useState的底层渲染机理。首先,我知道useState是React Hooks的一部分,用于在函数组件中添加状态。但底层是如何工作的呢?可能涉及到React的调度器、Fiber架构以及闭包等概念。 首先,React使用F…...
Cocos Creator 3.8 2D 游戏开发知识点整理
目录 Cocos Creator 3.8 2D 游戏开发知识点整理 1. Cocos Creator 3.8 概述 2. 2D 游戏核心组件 (1) 节点(Node)与组件(Component) (2) 渲染组件 (3) UI 组件 3. 动画系统 (1) 传统帧动画 (2) 动画编辑器 (3) Spine 和 …...
Java创建对象有几种方式?
大家好,我是锋哥。今天分享关于【Java创建对象有几种方式?】面试题。希望对大家有帮助; Java创建对象有几种方式? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Java 中,创建对象有几种常见的方式,具体如下&…...
R 字符串:深入理解与高效应用
R 字符串:深入理解与高效应用 引言 在R语言中,字符串是数据处理和编程中不可或缺的一部分。无论是数据清洗、数据转换还是数据分析,字符串的处理都是基础技能。本文将深入探讨R语言中的字符串概念,包括其基本操作、常见函数以及高效应用方法。 字符串基本概念 字符串定…...
基于Flask的全国星巴克门店可视化分析系统的设计与实现
【FLask】基于Flask的全国星巴克门店可视化分析系统的设计与实现(完整系统源码开发笔记详细部署教程)✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用Python作为主要开发语言,结合Flask框架进行后端开发&…...
pytorch实现半监督学习
人工智能例子汇总:AI常见的算法和例子-CSDN博客 半监督学习(Semi-Supervised Learning,SSL)结合了有监督学习和无监督学习的特点,通常用于部分数据有标签、部分数据无标签的场景。其主要步骤如下: 1. 数…...
Golang :用Redis构建高效灵活的应用程序
在当前的应用程序开发中,高效的数据存储和检索的必要性已经变得至关重要。Redis是一个快速的、开源的、内存中的数据结构存储,为各种应用场景提供了可靠的解决方案。在这个完整的指南中,我们将学习什么是Redis,通过Docker Compose…...
deepseek+vscode自动化测试脚本生成
近几日Deepseek大火,我这里也尝试了一下,确实很强。而目前vscode的AI toolkit插件也已经集成了deepseek R1,这里就介绍下在vscode中利用deepseek帮助我们完成自动化测试脚本的实践分享 安装AI ToolKit并启用Deepseek 微软官方提供了一个针对AI辅助的插件,也就是 AI Toolk…...
49【服务器介绍】
服务器和你的电脑可以说是一模一样的,只不过用途不一样,叫法就不一样了 物理服务器和云服务器的区别 整台设备眼睛能够看得到的,我们一般称之为物理服务器。所以物理服务器是比较贵的,不是每一个开发者都能够消费得起的。 …...
【大数据技术】Day07:本机DataGrip远程连接虚拟机MySQL/Hive
本机DataGrip远程连接虚拟机MySQL/Hive datagrip-2024.3.4VMware Workstation Pro 16CentOS-Stream-10-latest-x86_64-dvd1.iso写在前面 本文主要介绍如何使用本机的DataGrip连接虚拟机的MySQL数据库和Hive数据库,提高编程效率。 安装DataGrip 请按照以下步骤安装DataGrip软…...
大语言模型的个性化综述 ——《Personalization of Large Language Models: A Survey》
摘要: 本文深入解读了论文“Personalization of Large Language Models: A Survey”,对大语言模型(LLMs)的个性化领域进行了全面剖析。通过详细阐述个性化的基础概念、分类体系、技术方法、评估指标以及应用实践,揭示了…...
[论文学习]Adaptively Perturbed Mirror Descent for Learning in Games
[论文学习]Adaptively Perturbed Mirror Descent for Learning in Games 前言概述前置知识和问题约定单调博弈(monotone game)Nash均衡和Gap函数文章问题定义Mirror Descent 方法评价 前言 文章链接 我们称集合是紧的,则集合满足࿱…...
大语言模型概述
一、主流大语言模型(LLMs) GPT系列(OpenAI) 基于Transformer解码器架构,以生成能力著称,代表产品包括ChatGPT(GPT-3.5/4),支持多轮对话、文本生成和复杂推理。其优势在于…...
【Unity踩坑】Unity项目管理员权限问题(Unity is running as administrator )
问题描述: 使用Unity Hub打开或新建项目时会有下面的提示。 解决方法: 打开“本地安全策略”: 在Windows搜索栏中输入secpol.msc并回车,或者从“运行”对话框(Win R,然后输入secpol.msc)启…...
深入理解Node.js_架构与最佳实践
1. 引言 1.1 什么是Node.js Node.js简介:Node.js是一个基于Chrome V8引擎的JavaScript运行时,用于构建快速、可扩展的网络应用。Node.js的历史背景和发展:Node.js最初由Ryan Dahl在2009年发布,旨在解决I/O密集型应用的性能问题。随着时间的推移,Node.js社区不断壮大,提供…...
一文讲解Java中的ArrayList和LinkedList
ArrayList和LinkedList有什么区别? ArrayList 是基于数组实现的,LinkedList 是基于链表实现的。 二者用途有什么不同? 多数情况下,ArrayList更利于查找,LinkedList更利于增删 由于 ArrayList 是基于数组实现的&#…...
使用 DeepSeek-R1 与 AnythingLLM 搭建本地知识库
一、下载地址Download Ollama on macOS 官方网站:Ollama 官方模型库:library 二、模型库搜索 deepseek r1 deepseek-r1:1.5b 私有化部署deepseek,模型库搜索 deepseek r1 运行cmd复制命令:ollama run deepseek-r1:1.5b 私有化…...
MapReduce分区
目录 1. MapReduce分区1.1 哈希分区1.2 自定义分区 2. 成绩分组2.1 Map2.2 Partition2.3 Reduce 3. 代码和结果3.1 pom.xml中依赖配置3.2 工具类util3.3 GroupScores3.4 结果 参考 本文引用的Apache Hadoop源代码基于Apache许可证 2.0,详情请参阅 Apache许可证2.0。…...
【Spring】Spring Cloud Alibaba 版本选择及项目搭建笔记
文章目录 前言1. 版本选择2. 集成 Nacos3. 服务间调用4. 集成 Sentinel5. 测试后记 前言 最近重新接触了 Spring Cloud 项目,为此参考多篇官方文档重新搭建一次项目,主要实践: 版本选择,包括 Spring Cloud Alibaba、Spring Clou…...
C语言实现统计字符串中不同ASCII字符个数
在C语言编程中,经常会遇到一些对字符串进行处理的需求,今天我们就来探讨如何统计给定字符串中ASCII码在0 - 127范围内不同字符的个数。这不仅是一个常见的算法问题,也有助于我们更好地理解C语言中数组和字符操作的相关知识。 问题描述 对于给…...
保姆级教程Docker部署Zookeeper官方镜像
目录 1、安装Docker及可视化工具 2、创建挂载目录 3、运行Zookeeper容器 4、Compose运行Zookeeper容器 5、查看Zookeeper运行状态 6、验证Zookeeper是否正常运行 1、安装Docker及可视化工具 Docker及可视化工具的安装可参考:Ubuntu上安装 Docker及可视化管理…...
DeepSeek R1 简易指南:架构、本地部署和硬件要求
DeepSeek 团队近期发布的DeepSeek-R1技术论文展示了其在增强大语言模型推理能力方面的创新实践。该研究突破性地采用强化学习(Reinforcement Learning)作为核心训练范式,在不依赖大规模监督微调的前提下显著提升了模型的复杂问题求解能力。 技…...
Ollama教程:轻松上手本地大语言模型部署
Ollama教程:轻松上手本地大语言模型部署 在大语言模型(LLM)飞速发展的今天,越来越多的开发者希望能够在本地部署和使用这些模型,以便更好地控制数据隐私和计算资源。Ollama作为一个开源工具,旨在简化大语言…...
并行计算、分布式计算与云计算:概念剖析与对比研究(表格对比)
什么是并行计算?什么是分布计算?什么是云计算?我们如何更好理解这3个概念,我们采用概念之间的区别和联系的方式来理解,做到切实理解,深刻体会。 1、并行计算与分布式计算 并行计算、分布式计算都属于高性…...
Java牙科诊所管理系统web医院病例挂号预约平台springboot/ssm代码编写
Java牙科诊所管理系统web医院病例挂号预约平台springboot/ssm代码编写 基于springboot(可改ssm)htmlvue项目 开发语言:Java 框架:springboot/可改ssm vue JDK版本:JDK1.8(或11) 服务器:tomcat 数据库&…...
【Linux系统】信号:再谈OS与内核区、信号捕捉、重入函数与 volatile
再谈操作系统与内核区 1、浅谈虚拟机和操作系统映射于地址空间的作用 我们调用任何函数(无论是库函数还是系统调用),都是在各自进程的地址空间中执行的。无论操作系统如何切换进程,它都能确保访问同一个操作系统实例。换句话说&am…...
自定义数据集 使用paddlepaddle框架实现逻辑回归
导入必要的库 import numpy as np import paddle import paddle.nn as nn 数据准备: seed1 paddle.seed(seed)# 1.散点输入 定义输入数据 data [[-0.5, 7.7], [1.8, 98.5], [0.9, 57.8], [0.4, 39.2], [-1.4, -15.7], [-1.4, -37.3], [-1.8, -49.1], [1.5, 75.6…...
LabVIEW图片识别逆向建模系统
本文介绍了一个基于LabVIEW的图片识别逆向建模系统的开发过程。系统利用LabVIEW的强大视觉处理功能,通过二维图片快速生成对应的三维模型,不仅降低了逆向建模的技术门槛,还大幅提升了建模效率。 项目背景 在传统的逆向建模过程中…...
MySQL(高级特性篇) 13 章——事务基础知识
一、数据库事务概述 事务是数据库区别于文件系统的重要特性之一 (1)存储引擎支持情况 SHOW ENGINES命令来查看当前MySQL支持的存储引擎都有哪些,以及这些存储引擎是否支持事务能看出在MySQL中,只有InnoDB是支持事务的 &#x…...
