方法一:将私钥存入环境变量,环境变量指什么//spring中,rsa私钥应该怎么处置

news2025/2/5 21:02:54

环境变量(Environment Variables)是操作系统提供的一种机制,用于存储和传递配置信息或敏感数据(如密钥、密码等)。每个进程都可以访问一组环境变量,这些变量在操作系统级别定义,可以被应用程序读取和使用。

在 Spring 应用中,将私钥存入环境变量是一种常见的做法,可以避免将敏感信息硬编码在代码或配置文件中,从而提高安全性。


1. 什么是环境变量?

环境变量是操作系统级别的键值对(Key-Value),用于存储配置信息。例如:

  • JAVA_HOME:指向 Java 安装路径。
  • PATH:定义可执行文件的搜索路径。
  • RSA_PRIVATE_KEY:存储 RSA 私钥。

环境变量可以在以下场景中使用:

  • 操作系统启动时加载。
  • 应用程序运行时读取。
  • 通过命令行或脚本设置。

2. 如何设置环境变量?

2.1 在 Linux/MacOS 中设置
  1. 临时设置(仅在当前终端会话有效):

    export RSA_PRIVATE_KEY="MIIEvQIBADANBgkqhkiG9w0BAQEFAASC..."
    
  2. 永久设置(对所有终端会话有效):

    • 编辑 ~/.bashrc~/.zshrc 文件:
      echo 'export RSA_PRIVATE_KEY="MIIEvQIBADANBgkqhkiG9w0BAQEFAASC..."' >> ~/.bashrc
      source ~/.bashrc
      
2.2 在 Windows 中设置
  1. 临时设置(仅在当前命令行窗口有效):

    set RSA_PRIVATE_KEY=MIIEvQIBADANBgkqhkiG9w0BAQEFAASC...
    
  2. 永久设置(对所有命令行窗口有效):

    • 打开“系统属性” → “高级” → “环境变量”。
    • 在“系统变量”或“用户变量”中添加 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. 环境变量的安全性

优点
  • 避免硬编码:私钥不直接写在代码中,降低泄露风险。
  • 动态配置:不同环境(开发、测试、生产)可以使用不同的私钥。
  • 集中管理:通过操作系统或容器平台统一管理环境变量。
缺点
  • 访问控制:需确保只有授权用户和进程可以访问环境变量。
  • 泄露风险:如果服务器被入侵,环境变量可能被窃取。
最佳实践
  1. 限制访问权限
    • 确保只有应用进程可以读取环境变量。
    • 使用操作系统权限控制(如 Linux 的 chmodchown)。
  2. 加密存储
    • 在容器平台(如 Kubernetes)中使用 Secrets 存储环境变量。
  3. 日志安全
    • 避免在日志中打印环境变量。

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;

    @PostConstruct
    public 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 {

    @Autowired
    private 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:通过环境变量注入
实现步骤
  1. 将私钥存入环境变量

    # Linux/MacOS
    export RSA_PRIVATE_KEY="MIIEvQIBADANBgkqhkiGw..."
    
    # Windows (PowerShell)
    $env:RSA_PRIVATE_KEY="MIIEvQIBADANBgkqhkiGw..."
    
  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;
    
        @PostConstruct
        public 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)
实现步骤
  1. 添加 Jasypt 依赖

    <dependency>
        <groupId>com.github.ulisesbocchio</groupId>
        <artifactId>jasypt-spring-boot-starter</artifactId>
        <version>3.0.5</version>
    </dependency>
    
  2. 加密私钥

    # 使用 Jasypt 加密私钥
    java -cp jasypt-1.9.3.jar org.jasypt.intf.cli.JasyptPBEStringEncryptionCLI \
      input="MIIEvQIBADANBgkqhkiGw..." \
      password=your-secret-key \
      algorithm=PBEWithMD5AndDES
    
  3. 配置加密后的私钥

    # application.properties
    rsa.private-key=ENC(加密后的字符串)
    
  4. 启动时提供解密密钥

    java -jar your-app.jar -Djasypt.encryptor.password=your-secret-key
    
  5. 在代码中解密

    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 为例)
  1. 将私钥存储在 AWS KMS

    • 通过 AWS 控制台或 SDK 创建一个加密密钥(CMK)。
  2. 在 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);
        }
    }
    
  3. 使用解密后的私钥

    @Service
    public class AuthService {
    
        @Autowired
        private AwsKmsService kmsService;
    
        public PrivateKey loadPrivateKey() throws Exception {
            byte[] encryptedKey = // 从数据库或安全存储中加载加密的私钥
            String privateKeyStr = kmsService.decryptPrivateKey(encryptedKey);
            // 转换为 PrivateKey 对象(同方案1)
        }
    }
    
优点
  • 私钥由 AWS 托管,支持自动轮换和访问控制。
  • 适合云原生应用。

方案 4:硬件安全模块(HSM)
实现步骤
  1. 将私钥存储在 HSM

    • 使用 HSM 设备(如 SafeNet Luna)生成并存储密钥。
  2. 通过 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。
  • 适合金融、政府等高安全场景。

三、最佳实践

  1. 最小化权限
    • 限制服务器和环境变量的访问权限,仅允许应用进程读取私钥。
  2. 密钥轮换
    • 定期更换密钥对(如每 3 个月一次),旧密钥仅用于解密历史数据。
  3. 审计与监控
    • 记录私钥的使用日志,监控异常访问行为。
  4. 代码审查
    • 使用 Git Hooks 或扫描工具(如 TruffleHog)防止私钥提交到仓库。

四、总结

  • 推荐方案
    • 开发环境:环境变量或 Jasypt 加密配置文件。
    • 生产环境:AWS KMS、HashiCorp Vault 或 HSM。
  • 核心原则
    • 私钥不落地(不硬编码、不明文存储)。
    • 依赖硬件或云服务提供商的密钥管理能力。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2293470.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java创建对象有几种方式?

大家好&#xff0c;我是锋哥。今天分享关于【Java创建对象有几种方式?】面试题。希望对大家有帮助&#xff1b; Java创建对象有几种方式? 1000道 互联网大厂Java工程师 精选面试题-Java资源分享网 在 Java 中&#xff0c;创建对象有几种常见的方式&#xff0c;具体如下&…

基于Flask的全国星巴克门店可视化分析系统的设计与实现

【FLask】基于Flask的全国星巴克门店可视化分析系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 该系统采用Python作为主要开发语言&#xff0c;结合Flask框架进行后端开发&…

Golang :用Redis构建高效灵活的应用程序

在当前的应用程序开发中&#xff0c;高效的数据存储和检索的必要性已经变得至关重要。Redis是一个快速的、开源的、内存中的数据结构存储&#xff0c;为各种应用场景提供了可靠的解决方案。在这个完整的指南中&#xff0c;我们将学习什么是Redis&#xff0c;通过Docker Compose…

deepseek+vscode自动化测试脚本生成

近几日Deepseek大火,我这里也尝试了一下,确实很强。而目前vscode的AI toolkit插件也已经集成了deepseek R1,这里就介绍下在vscode中利用deepseek帮助我们完成自动化测试脚本的实践分享 安装AI ToolKit并启用Deepseek 微软官方提供了一个针对AI辅助的插件,也就是 AI Toolk…

【大数据技术】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》

摘要&#xff1a; 本文深入解读了论文“Personalization of Large Language Models: A Survey”&#xff0c;对大语言模型&#xff08;LLMs&#xff09;的个性化领域进行了全面剖析。通过详细阐述个性化的基础概念、分类体系、技术方法、评估指标以及应用实践&#xff0c;揭示了…

[论文学习]Adaptively Perturbed Mirror Descent for Learning in Games

[论文学习]Adaptively Perturbed Mirror Descent for Learning in Games 前言概述前置知识和问题约定单调博弈&#xff08;monotone game&#xff09;Nash均衡和Gap函数文章问题定义Mirror Descent 方法评价 前言 文章链接 我们称集合是紧的&#xff0c;则集合满足&#xff1…

【Unity踩坑】Unity项目管理员权限问题(Unity is running as administrator )

问题描述&#xff1a; 使用Unity Hub打开或新建项目时会有下面的提示。 解决方法&#xff1a; 打开“本地安全策略”&#xff1a; 在Windows搜索栏中输入secpol.msc并回车&#xff0c;或者从“运行”对话框&#xff08;Win R&#xff0c;然后输入secpol.msc&#xff09;启…

一文讲解Java中的ArrayList和LinkedList

ArrayList和LinkedList有什么区别&#xff1f; ArrayList 是基于数组实现的&#xff0c;LinkedList 是基于链表实现的。 二者用途有什么不同&#xff1f; 多数情况下&#xff0c;ArrayList更利于查找&#xff0c;LinkedList更利于增删 由于 ArrayList 是基于数组实现的&#…

使用 DeepSeek-R1 与 AnythingLLM 搭建本地知识库

一、下载地址Download Ollama on macOS 官方网站&#xff1a;Ollama 官方模型库&#xff1a;library 二、模型库搜索 deepseek r1 deepseek-r1:1.5b 私有化部署deepseek&#xff0c;模型库搜索 deepseek r1 运行cmd复制命令&#xff1a;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&#xff0c;详情请参阅 Apache许可证2.0。…

【Spring】Spring Cloud Alibaba 版本选择及项目搭建笔记

文章目录 前言1. 版本选择2. 集成 Nacos3. 服务间调用4. 集成 Sentinel5. 测试后记 前言 最近重新接触了 Spring Cloud 项目&#xff0c;为此参考多篇官方文档重新搭建一次项目&#xff0c;主要实践&#xff1a; 版本选择&#xff0c;包括 Spring Cloud Alibaba、Spring Clou…

C语言实现统计字符串中不同ASCII字符个数

在C语言编程中&#xff0c;经常会遇到一些对字符串进行处理的需求&#xff0c;今天我们就来探讨如何统计给定字符串中ASCII码在0 - 127范围内不同字符的个数。这不仅是一个常见的算法问题&#xff0c;也有助于我们更好地理解C语言中数组和字符操作的相关知识。 问题描述 对于给…

保姆级教程Docker部署Zookeeper官方镜像

目录 1、安装Docker及可视化工具 2、创建挂载目录 3、运行Zookeeper容器 4、Compose运行Zookeeper容器 5、查看Zookeeper运行状态 6、验证Zookeeper是否正常运行 1、安装Docker及可视化工具 Docker及可视化工具的安装可参考&#xff1a;Ubuntu上安装 Docker及可视化管理…

DeepSeek R1 简易指南:架构、本地部署和硬件要求

DeepSeek 团队近期发布的DeepSeek-R1技术论文展示了其在增强大语言模型推理能力方面的创新实践。该研究突破性地采用强化学习&#xff08;Reinforcement Learning&#xff09;作为核心训练范式&#xff0c;在不依赖大规模监督微调的前提下显著提升了模型的复杂问题求解能力。 技…

【Linux系统】信号:再谈OS与内核区、信号捕捉、重入函数与 volatile

再谈操作系统与内核区 1、浅谈虚拟机和操作系统映射于地址空间的作用 我们调用任何函数&#xff08;无论是库函数还是系统调用&#xff09;&#xff0c;都是在各自进程的地址空间中执行的。无论操作系统如何切换进程&#xff0c;它都能确保访问同一个操作系统实例。换句话说&am…

自定义数据集 使用paddlepaddle框架实现逻辑回归

导入必要的库 import numpy as np import paddle import paddle.nn as nn 数据准备&#xff1a; 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的强大视觉处理功能&#xff0c;通过二维图片快速生成对应的三维模型&#xff0c;不仅降低了逆向建模的技术门槛&#xff0c;还大幅提升了建模效率。 ​ 项目背景 在传统的逆向建模过程中&#xf…

MySQL(高级特性篇) 13 章——事务基础知识

一、数据库事务概述 事务是数据库区别于文件系统的重要特性之一 &#xff08;1&#xff09;存储引擎支持情况 SHOW ENGINES命令来查看当前MySQL支持的存储引擎都有哪些&#xff0c;以及这些存储引擎是否支持事务能看出在MySQL中&#xff0c;只有InnoDB是支持事务的 &#x…

前端进阶:深度剖析预解析机制

一、预解析是什么&#xff1f; 在前端开发中&#xff0c;我们常常会遇到一些看似不符合常规逻辑的代码执行现象&#xff0c;比如为什么在变量声明之前访问它&#xff0c;得到的结果是undefined&#xff0c;而不是报错&#xff1f;为什么函数在声明之前就可以被调用&#xff1f…