首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 綜合教學

Spring MVC 生產環境數據源憑證隱藏方案:自定義 PropertyPlaceholderConfigurer 實現敏感配置外部化

     編輯:Java 綜合教學

痛點:明文配置的安全隱患

<!-- 典型明文配置 -->
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="location" value="file:/opt/config/jdbc.properties"/>
</bean>

<!-- jdbc.properties -->
driver=com.mysql.jdbc.Driver
url=jdbc:mysql://192.168.1.100:3306/prod_db
username=admin
password=P@ssw0rd123  <!-- 高風險!-->

配置文件一旦洩露(Git 誤提交、服務器入侵、備份文件流出),數據庫直裸奔運行環境。

解決方案:配置外部化 + 運行時解密/注入

架構圖解

┌──────────────┐     ┌─────────────────────┐     ┌──────────────┐
│ 應用啟動     │────▶│ CustomProperty      │────▶│ 數據源 Bean  │
│ 讀取加密配置 │     │ PlaceholderConfigurer│     │ 獲取解密值   │
└──────────────┘     │ 1. 讀取加密 properties
                     │ 2. 識別敏感 key
                     │ 3. 從安全存儲獲取明文
                     │ 4. 覆蓋屬性值
                     └─────────────────────┘

核心實現:繼承 PropertyPlaceholderConfigurer

public class EncryptPropertyPlaceholderConfigurer 
        extends PropertyPlaceholderConfigurer {

    // 敏感屬性名單
    private static final Set<String> SENSITIVE_KEYS = Set.of(
        "jdbc.url", "jdbc.username", "jdbc.password"
    );

    @Override
    protected String convertProperty(String propertyName, String propertyValue) {
        if (SENSITIVE_KEYS.contains(propertyName)) {
            // 從安全中心獲取明文(示例:調用內部服務/讀取密文解密)
            String decrypted = SecureConfigCenter.getDecryptedValue(propertyName);
            if (decrypted != null) {
                return decrypted; // 返回明文覆蓋佔位符
            }
        }
        return super.convertProperty(propertyName, propertyValue); // 非敏感走默認邏輯
    }
}

Spring XML 接入

<bean class="com.example.config.EncryptPropertyPlaceholderConfigurer">
    <property name="location" value="file:/opt/config/jdbc.properties"/>
</bean>

<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
    <property name="driverClassName" value="${jdbc.driver}"/>
    <property name="url" value="${jdbc.url}"/>
    <property name="username" value="${jdbc.username}"/>
    <property name="password" value="${jdbc.password}"/>
</bean>

配置文件僅保留佔位符

# jdbc.properties(可安全提交 Git、備份)
jdbc.driver=com.mysql.jdbc.Driver
jdbc.url=ENCRYPTED_PLACEHOLDER
jdbc.username=ENCRYPTED_PLACEHOLDER
jdbc.password=ENCRYPTED_PLACEHOLDER

安全存儲方案對比

進階:WebService 遠程獲取憑證(雙向 SSL + 非對稱加密)

  1. 應用啟動時調用內部授權服務(WebService/REST)。
  2. 雙向 HTTPS 驗證雙方身份(雙向 SSL)。
  3. 請求體非對稱加密(RSA/OAEP),響應體對稱加密(AES-GCM)。
  4. 授權服務校驗應用身份、IP 白名單、時間窗口後返回明文憑證。
  5. 應用內存中構建 DataSource,不落盤、不打日誌。

此方案需配合 啟動順序控制(先啟授權服務)、熔斷降級(授權服務不可用時走本地緩存)、定期輪換機制。

最佳實踐清單

  • ✅ 絕不將明文密碼提交至版本控制(Git/SVN)。
  • ✅ 配置文件僅保留佔位符或密文。
  • ✅ 敏感屬性識別白名單機制,避免誤解密普通屬性。
  • ✅ 解密邏輯異常時快速失敗,啟動階段暴露問題。
  • ✅ 日誌脫敏:覆寫 toString()、Logback 模式排除 password 字段。
  • ✅ 生產環境禁用 JMX/Actuator 敏感端點或加強認證。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
方案實現方式安全等級運維複雜度適用場景
環境變量K8s Secret / Docker ENV / 系統環境變量⭐⭐⭐低容器化部署、雲原生
配置中心Apollo / Nacos / Consul + 加密存儲⭐⭐⭐⭐中微服務、動態刷新、審計
密碼管理器HashiCorp Vault / AWS Secrets Manager⭐⭐⭐⭐⭐高高合規要求、動態憑證輪換
對稱加密文件AES 加密 properties,啟動時解密⭐⭐低單體應用、無配置中心