1. 程式人生 > 程式設計 >Spring Boot 實現配置檔案加解密原理

Spring Boot 實現配置檔案加解密原理

背景

接上文《失蹤人口迴歸,mybatis-plus 3.3.2 釋出》[1] ,提供了一個非常實用的功能 「資料安全保護」 功能,不僅支援資料來源的配置加密,對於 spring boot 全域性的 yml /properties 檔案均可實現敏感資訊加密功能,在一定的程度上控制開發人員流動導致敏感資訊洩露。

// 資料來源敏感資訊加密

spring:
 datasource:
  url: mpw:qRhvCwF4GOqjessEB3G+a5okP+uXXr96wcucn2Pev6BfaoEMZ1gVpPPhdDmjQqoM
  password: mpw:Hzy5iliJbwDHhjLs1L0j6w==
  username: mpw:Xb+EgsyuYRXw7U7sBJjBpA==

// 資料來源敏感資訊加密

spring:
 redis:
  password: mpw:Hzy5iliJbwDHhjLs1L0j6w==

實現原理

我們翻開 spring boot 官方文件,翻到 4.2.6 章節 Spring Boot 不提供對加密屬性值的任何內建支援,但是提供修改 Spring 環境中包含的值所必需的擴充套件點 EnvironmentPostProcessor 允許在應用程式之前操作環境屬性值

Spring Boot 實現配置檔案加解密原理

mybatis-plus 的實現

public class SafetyEncryptProcessor implements EnvironmentPostProcessor {

 @Override
 public void postProcessEnvironment(ConfigurableEnvironment environment,SpringApplication application) {
 //命令列中獲取金鑰
 String mpwKey = null;

 // 返回全部形式的配置源(環境變數、命令列引數、配置檔案 ...)
 for (PropertySource<?> ps : environment.getPropertySources()) {
  // 判斷是否需要含有加密密碼,沒有就直接跳過
  if (ps instanceof SimpleCommandLinePropertySource) {
  SimpleCommandLinePropertySource source = (SimpleCommandLinePropertySource) ps;
  mpwKey = source.getProperty("mpw.key");
  break;
  }
 }

 //處理加密內容(獲取到原有配置,然後解密放到新的map 裡面(key是原有key))
 HashMap<String,Object> map = new HashMap<>();
 for (PropertySource<?> ps : environment.getPropertySources()) {
  if (ps instanceof OriginTrackedMapPropertySource) {
  OriginTrackedMapPropertySource source = (OriginTrackedMapPropertySource) ps;
  for (String name : source.getPropertyNames()) {
   Object value = source.getProperty(name);
   if (value instanceof String) {
   String str = (String) value;
   if (str.startsWith("mpw:")) {
    map.put(name,AES.decrypt(str.substring(4),mpwKey));
   }
   }
  }
  }
 }
 // 將解密的資料放入環境變數,並處於第一優先順序上 (這裡一定要注意,覆蓋其他配置)
 if (!map.isEmpty()) {
  environment.getPropertySources().addFirst(new MapPropertySource("custom-encrypt",map));
 }
 }
}

如何載入生效

resources/META-INF/spring.factories 配置 SPI

org.springframework.boot.env.EnvironmentPostProcessor=\
 com.baomidou.mybatisplus.autoconfigure.SafetyEncryptProcessor

擴充套件

mybatis-plus 預設是讀取啟動引數,可以在此處可以根據自己需求修改為更安全的根金鑰儲存。

讀取環境變數

System.getProperty("mpw.key")

遠端載入密碼服務

// 此處思路,參考 druid ConfigFilter
public Properties loadConfig(String filePath) {
   Properties properties = new Properties();

   InputStream inStream = null;
   try {
     boolean xml = false;
     if (filePath.startsWith("file://")) {
       filePath = filePath.substring("file://".length());
       inStream = getFileAsStream(filePath);
       xml = filePath.endsWith(".xml");
     } else if (filePath.startsWith("http://") || filePath.startsWith("https://")) {
       URL url = new URL(filePath);
       inStream = url.openStream();
       xml = url.getPath().endsWith(".xml");
     } else if (filePath.startsWith("classpath:")) {
       String resourcePath = filePath.substring("classpath:".length());
       inStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resourcePath);
       // 在classpath下應該也可以配置xml檔案吧?
       xml = resourcePath.endsWith(".xml");
     } else {
       inStream = getFileAsStream(filePath);
       xml = filePath.endsWith(".xml");
     }

     if (inStream == null) {
       LOG.error("load config file error,file : " + filePath);
       return null;
     }

     if (xml) {
       properties.loadFromXML(inStream);
     } else {
       properties.load(inStream);
     }

     return properties;
   } catch (Exception ex) {
     LOG.error("load config file error,file : " + filePath,ex);
     return null;
   } finally {
     JdbcUtils.close(inStream);
   }
 }

總結

配置檔案加解密,是通過自定義擴充套件 EnvironmentPostProcessor 實現
若專案中沒有使用最新版本 mybatis-plus ,可以參考如上自己實現,不過我推薦 jasypt-spring-boot-starter[2],原理類似實現了一個 EnableEncryptablePropertySourcesPostProcessor,但是支援的加密方式更多更成熟
關於 jasypt 使用可以參考原始碼: https://gitee.com/log4j/pig

到此這篇關於Spring Boot 實現配置檔案加解密原理的文章就介紹到這了,更多相關SpringBoot檔案加解密內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!