數據庫密碼配置項都不加密?心也太大了吧!

image


先看一份典型的配置文件

... 省略 ...

## 配置MySQL數據庫鏈接
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://121.196.xxx.xxx:3306/user?useUnicode=true&characterEncoding=utf-8
spring.datasource.username=root
spring.datasource.password=123456

## 配置Redis緩存鏈接
redis.host=121.196.xxx.xxx
redis.port=6379
redis.password=111111

## 配置SMS短信服務鏈接
ali.sms.access_key_id=2zHmLdxAes7Bbe2w  
ali.sms.access_key_secret=bImWdv6iy0him8ly

... 省略 ...

這是節選自某個典型的Spring Boot項目的application.properties配置文件。java

噓... 偷偷告訴我,是否是不少小夥伴也都是這麼寫的?

這乍一看沒啥問題,不少人會以爲理所固然。包括我本身也看到過不少的項目(包括不少開源項目)是這麼寫的。mysql

但仔細一琢磨,發現:git

image

是的! 不少項目的配置文件裏,包括數據庫密碼、緩存密碼、亦或是一些第三方服務的Key都是直接配在裏面,沒有作任何加密處理!程序員

有人會說這個配置文件反正是我本身的,有啥風險?github

這個嘛,以前卻是看到過一個例子,一個程序員把本身公司的項目代碼上傳到了本身的GitHub倉庫裏了,結果配置文件忘了處理,致使公司數據庫泄露,關鍵問題是,這個公司仍是個酒店管理公司,所以後果可想而知了...redis

image

換個角度想,假如當時那個項目的配置文件裏,全部重要信息都通過了加密,那這一幕大機率就不會發生了。因此,即便是項目的配置文件,重要的信息也得加密!spring


哪些信息要加密呢?

通常來講,項目配置文件裏,全部涉及信息安全的配置項(或字段)都應該作處理,典型的好比:sql

  • 用到的數據庫、緩存的密碼
  • 用到的中間件、消息隊列的密碼
  • 用到的各類第三方服務的Access_Key
  • 其餘第三方服務的通訊信息
  • ......等等

總而言之,關鍵字段都應該保護起來,最起碼不能用明文直接寫在配置文件裏!數據庫


如何加密配置項呢?

方法很是簡單,幾個步驟便可完成,先來演示一個最簡版本:緩存

一、首先創建一個基礎的Spring Boot工程

這就再也不贅述了

二、引入jasypt-spring-boot加密組件

經過jasypt-spring-boot這個開箱即用的加密組件來引入Jasypt這個強大的加密庫

<dependency>
    <groupId>com.github.ulisesbocchio</groupId>
    <artifactId>jasypt-spring-boot-starter</artifactId>
    <version>3.0.2</version>
</dependency>

三、配置加密密鑰

在Spring Boot的項目配置文件application.properties裏新增以下配置:

jasypt.encryptor.password=CodeSheep

能夠理解爲jasypt會使用這個自定義加密密鑰,對配置文件裏的重要項進行加密。

四、加密測試

爲了便於測試,咱們直接擴展Spring Boot項目的啓動類,項目啓動時執行加密測試代碼,直接看效果

@SpringBootApplication
public class SpringBootConfigEncryptApplication implements CommandLineRunner {

    @Autowired
    private ApplicationContext appCtx;

    @Autowired
    private StringEncryptor codeSheepEncryptorBean;

    public static void main(String[] args) {
        SpringApplication.run(SpringBootConfigEncryptApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        Environment environment = appCtx.getBean(Environment.class);

        // 首先獲取配置文件裏的原始明文信息
        String mysqlOriginPswd = environment.getProperty("spring.datasource.password");
        String redisOriginPswd = environment.getProperty("redis.password");
        String aliSmsOriginAk = environment.getProperty("ali.sms.access_key_secret");

        // 加密
        String mysqlEncryptedPswd = encrypt( mysqlOriginPswd );
        String redisEncryptedPswd = encrypt( redisOriginPswd );
        String aliSmsEncryptedAk = encrypt( aliSmsOriginAk );

        // 打印加密先後的結果對比
        System.out.println( "MySQL原始明文密碼爲:" + mysqlOriginPswd );
        System.out.println( "Redis原始明文密碼爲:" + redisOriginPswd );
        System.out.println( "阿里雲SMS原始AccessKey密碼爲:" + aliSmsOriginAk );
        System.out.println( "====================================" );
        System.out.println( "MySQL原始明文密碼加密後的結果爲:" + mysqlEncryptedPswd );
        System.out.println( "Redis原始明文密碼加密後的結果爲:" + redisEncryptedPswd );
        System.out.println( "阿里雲SMS原始AccessKey密碼加密後的結果爲:" + aliSmsEncryptedAk );
    }

    private String encrypt( String originPassord ) {
        String encryptStr = codeSheepEncryptorBean.encrypt( originPassord );
        return encryptStr;
    }

    private String decrypt( String encryptedPassword ) {
        String decryptStr = codeSheepEncryptorBean.decrypt( encryptedPassword );
        return decryptStr;
    }
}

運行項目,控制檯打印:

MySQL原始明文密碼爲:123456
Redis原始明文密碼爲:111111
阿里雲SMS原始AccessKey密碼爲:bImWdv13da894mly
====================================
MySQL原始明文密碼加密後的結果爲:IV7SyeQOfG4GhiXeGLboVgOLPDO+dJMDoOdmEOQp3KyVjruI+dKKeehsTriWPKbo
Redis原始明文密碼加密後的結果爲:litUkxJ3fN6+//Emq3vZ+y4o7ZOnZ8doOy7NrgJIDLoNWGG0m3ygGeQh/dEroKvv
阿里雲SMS原始AccessKey密碼加密後的結果爲:MAhrOs20DY0RU/c1IKyLCt6dWZqLLOO4wUcK9GBgSxNII3C+y+SRptors+FyNz55xNDslhDnpWllhcYPwZsO5A==

五、修改配置文件,替換待加密配置項

咱們拿到上一步獲得的加密結果,將配置文件中的原始明文密碼替換成上一步對應的結果便可,就像這樣:

image

因此牆裂建議配置文件裏的全部重要信息都這樣處理!

六、查看密碼解密結果

@SpringBootApplication
public class SpringBootConfigEncryptApplication implements CommandLineRunner {

    @Autowired
    private ApplicationContext appCtx;

    @Autowired
    private StringEncryptor codeSheepEncryptorBean;

    public static void main(String[] args) {
        SpringApplication.run(SpringBootConfigEncryptApplication.class, args);
    }

    @Override
    public void run(String... args) throws Exception {

        Environment environment = appCtx.getBean(Environment.class);

        // 首先獲取配置文件裏的配置項
        String mysqlOriginPswd = environment.getProperty("spring.datasource.password");
        String redisOriginPswd = environment.getProperty("redis.password");
        String aliSmsOriginAk = environment.getProperty("ali.sms.access_key_secret");

        // 打印解密後的結果
        System.out.println( "MySQL原始明文密碼爲:" + mysqlOriginPswd );
        System.out.println( "Redis原始明文密碼爲:" + redisOriginPswd );
        System.out.println( "阿里雲SMS原始AccessKey密碼爲:" + aliSmsOriginAk );
    }
}

打印結果:

MySQL原始明文密碼爲:123456
Redis原始明文密碼爲:111111
阿里雲SMS原始AccessKey密碼爲:bImWdv13da894mly

很明顯,在代碼中使用時,jasypt-spring-boot組件會自動將ENC()語法包裹的配置項加密字段自動解密,數據得以還原。


小朋友,你是否有不少問號?

image

這時候我想確定不少小夥伴表示疑惑,典型的好比:

一、加密密鑰必須放在ENC()中?爲何是ENC

二、雖說原始涉及信息安全的配置項被加密,可是自定義的加密密鑰jasypt.encryptor.password=CodeSheep假如泄露了,別人不仍是有概率能夠解密的嗎?

針對這些問題,繼續往下看。


自定義加密先後綴

若是不肯意使用jasypt默認提供的ENC來標記加密字段,徹底能夠換成自定義的先後綴標記,好比我想換成CodeSheep()來標記加密字段,此時只須要在配置文件裏配置一下先後綴便可:

jasypt.encryptor.property.prefix=CodeSheep(
jasypt.encryptor.property.suffix=)

這時候加密字段就能夠放在CodeSheep()標記的字段中:

image


讓加密更安全

雖然通過上文的加密,涉及信息安全的配置項確定會變得更安全,這個毋庸置疑!

可是假如配置文件裏的自定義加密密鑰jasypt.encryptor.password=CodeSheep泄露了,那咱們的加密字段也仍是有可能被別人解密,爲此,有幾項工做可讓加密變得更加安全。

一、使用自定義加密器

上文實驗加密時,使用的是默認的加密規則,這一點會讓當自定義加密密鑰泄漏時可能變得不安全。爲此咱們能夠自定義加密規則。

自定義加密規則很是簡單,只須要提供自定義的加密器配置類便可,好比我這裏自定義一個名爲 codeSheepEncryptorBean類型的加密器:

@Configuration
public class CodeSheepEncryptorCfg {

    @Bean( name = "codeSheepEncryptorBean" )
    public StringEncryptor codesheepStringEncryptor() {

        PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();

        SimpleStringPBEConfig config = new SimpleStringPBEConfig();
        config.setPassword("CodeSheep");
        config.setAlgorithm("PBEWITHHMACSHA512ANDAES_256");
        config.setKeyObtentionIterations("1000");
        config.setPoolSize("1");
        config.setProviderName("SunJCE");
        config.setSaltGeneratorClassName("org.jasypt.salt.RandomSaltGenerator");
        config.setIvGeneratorClassName("org.jasypt.iv.RandomIvGenerator");
        config.setStringOutputType("base64");
        encryptor.setConfig(config);

        return encryptor;
    }
}

注意這裏Bean的名字name是須要顯式指定的(默認的名字是jasyptStringEncryptor),若是像這裏同樣用的自定義名字,則還須要在Spring Boot的application.properties配置文件中來指定bean的名字,就像這樣:

jasypt.encryptor.bean=codeSheepEncryptorBean

二、加密密鑰不要寫在配置文件中

若是以爲上面這種方式仍是可能會致使加密密鑰泄露的話(畢竟仍是寫在了配置文件中),那咱們乾脆能夠直接將加密密鑰從配置文件中拿掉,取而代之的有三種方式

  • 方式一:直接做爲程序啓動時的命令行參數來帶入
java -jar yourproject.jar --jasypt.encryptor.password=CodeSheep
  • 方式二:直接做爲程序啓動時的應用環境變量來帶入
java -Djasypt.encryptor.password=CodeSheep -jar yourproject.jar
  • 方式三:甚至能夠做爲系統環境變量的方式來帶入

比方說,咱們提早設置好系統環境變量JASYPT_ENCRYPTOR_PASSWORD = CodeSheep,則直接在Spring Boot的項目配置文件中作以下配置便可:

jasypt.encryptor.password=${JASYPT_ENCRYPTOR_PASSWORD:}

這時候也會安全得多。

image


噓...

好了,說了這麼多,若是你項目的配置文件中的重要信息沒有加密的話,答應我,二話別說,趕快所有偷偷去改掉,快!速度!跑步前進!

image

相關文章
相關標籤/搜索