配置文件密碼用jasypt加密

我們一般都寫在yml或者properties文件中。

有沒有一種辦法,在配置文件中寫密文,程序啓動後自動解密,再使用這個解密後的密碼進行連數據庫或者redis?

jasypt就實現了這個功能。

https://github.com/ulisesbocchio/jasypt-spring-boot

這是jasypt的地址,上面有詳細的使用說明和例子。目前版本已經更新到3.0.2

參照說明,我們看怎麼使用。

目錄

1,引入依賴

2,yml文件配置jasypt屬性

3,用jasypt加密,在yml填寫加密後的密碼


1,引入依賴

<!-- jasypt方式一 -->
		<dependency>
			<groupId>com.github.ulisesbocchio</groupId>
			<artifactId>jasypt-spring-boot-starter</artifactId>
			<version>3.0.2</version>
		</dependency>
		
		<!-- jasypt方式二 -->
		<!-- <dependency>
			<groupId>com.github.ulisesbocchio</groupId>
			<artifactId>jasypt-spring-boot</artifactId>
			<version>3.0.2</version>
		</dependency> -->

2種方式引入依賴包。

第一種是你的springboot應用使用了@SpringBootApplication or @EnableAutoConfiguration註解就可以這樣引入。

如果沒有使用上面的註解,就用第二種方式。並且還需要在你的啓動類上加註解:

@Configuration
@EnableEncryptableProperties

package com.example.gate;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
//import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;

import com.ulisesbocchio.jasyptspringboot.annotation.EnableEncryptableProperties;


//使用jasypt的第二種方式.如果你沒用到@SpringBootApplication 或  @EnableAutoConfiguration就必須用下面2個註解,才能正常使用jasypt
//@Configuration
//@EnableEncryptableProperties

//@EnableCircuitBreaker
@ComponentScan(basePackages = "com.example")
@EnableDiscoveryClient
@SpringBootApplication
public class GateApplication {

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

	

}

其實還有更高級的用法,可以指定哪幾個配置文件用jasypt。

//使用jasypt的第二種方式.如果你沒用到@SpringBootApplication 或  @EnableAutoConfiguration就必須用下面2個註解,才能正常使用jasypt
//@Configuration
//@EnableEncryptableProperties

//具體指定配置文件的用法,其他配置文件不受jasypt影響
//@Configuration
//@EncryptablePropertySources({@EncryptablePropertySource("classpath:encrypted.properties"),
//                             @EncryptablePropertySource("classpath:encrypted2.properties")})

//@EnableCircuitBreaker
@ComponentScan(basePackages = "com.example")
@EnableDiscoveryClient
@SpringBootApplication
public class GateApplication {

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

	

}

 這個看你具體需要了。

2,yml文件配置jasypt屬性

#jasypt加密配置
jasypt:
  encryptor:
    password: miyao
    algorithm: PBEWITHHMACSHA512ANDAES_256
#    property:
#      prefix: "ENC@["
#      suffix: "]"

這是我給的一個配置。

其中祕鑰password是必須自己定義的。其他都可以不配置,因爲有默認的配置:

Key Required Default Value
jasypt.encryptor.password True -
jasypt.encryptor.algorithm False PBEWITHHMACSHA512ANDAES_256
jasypt.encryptor.key-obtention-iterations False 1000
jasypt.encryptor.pool-size False 1
jasypt.encryptor.provider-name False SunJCE
jasypt.encryptor.provider-class-name False null
jasypt.encryptor.salt-generator-classname False org.jasypt.salt.RandomSaltGenerator
jasypt.encryptor.iv-generator-classname False org.jasypt.iv.RandomIvGenerator
jasypt.encryptor.string-output-type False base64
jasypt.encryptor.proxy-property-sources False false
jasypt.encryptor.skip-property-sources False empty list

3,用jasypt加密,在yml填寫加密後的密碼

先說填寫密碼的格式:

#jasypt加密後的密碼
mypass:
  pass1: ENC(NfA+LtBfc26xLiHLb0EGXeNfU9TaE2tQIt7X94DrodPcUKV/tnTKQLz7bcLSM3i0)

面必須用ENC()包起來,這樣jasypt才能識別出來這個密碼需要解密再傳給應用程序。

這個密碼怎麼獲取呢?

方式有很多,

方法一:寫個工具類,把jasypt加密的過程寫出來,執行後得到密碼。

方法二:寫個controller,注入jasypt的加密對象,執行加密,把密碼打印或者返回到頁面

方法三:jasypt提供了加密的命令,

https://github.com/ulisesbocchio/jasypt-spring-boot

具體看上面的鏈接。這個其實意義不大。

 

我自己把前兩種方式的代碼貼出來:

工具類:


package com.example.gate.util;

import org.jasypt.encryption.StringEncryptor;
import org.jasypt.encryption.pbe.PooledPBEStringEncryptor;
import org.jasypt.encryption.pbe.config.SimpleStringPBEConfig;

/**
 * Jasypt用於在配置文件中寫加密後的密碼,只要配上祕鑰,讀入系統中的就是解密後的正確密碼。
 * 這個工具類主要是用於實驗Jasypt的加密和解密.
 * 把yml中對Jasypt的配置寫到代碼裏而已。
 * 
 * 實際使用Jasypt時,只需pom引入依賴,yml中配置相關項(祕鑰等),然後把加密後的密碼寫入你需要配置的地方(yml文件。。。)
 * 程序啓動後,會自動解密(如果程序不能正常解密,那你的系統啓動就有問題了,比如數據庫連不上,redis連不上等,都是密碼不正確的錯)
 * 我們也可以寫個controller把yml配置文件中的密碼打印出來,這個打印的肯定不是你寫的加密的字符串而是解密後的正確密碼。
 * 整個解密的過程是交給Jasypt做的。加密的過程是我們提前加密得到密文,寫到yml配置文件中的。但是必須有ENC()這個標識。
 * 
 * 
 * @author lsy
 *
 */
public class JasyptUtil {

	public static void main(final String[] args) {

		String miyao = "miyao";// 祕鑰字符串
		String pass = "123456";// 待加密的明文密碼
		try {
			StringEncryptor stringEncryptor = JasyptUtil.getInstance(miyao);
			String mima = stringEncryptor.encrypt(pass);
			System.out.println("【" + pass + "】被加密成【" + mima + "】");

			String jiemi = stringEncryptor.decrypt(mima);
			System.out.println("【" + mima + "】被解密成【" + jiemi + "】");

		} catch (Exception e) {
			e.printStackTrace();
		}
	}

	private static StringEncryptor stringEncryptor = null;//org.jasypt.encryption.StringEncryptor對象

	public static StringEncryptor getInstance(String miyao) throws Exception {
		if(miyao==null||miyao.trim().equals("")) {
			System.out.println("祕鑰不能爲空!");
			throw new Exception("org.jasypt.encryption.StringEncryptor祕鑰不能爲空!");
		}
		if (stringEncryptor == null) {
			PooledPBEStringEncryptor encryptor = new PooledPBEStringEncryptor();
			SimpleStringPBEConfig config = new SimpleStringPBEConfig();
			config.setPassword("miyao");// 這個祕鑰必須是我們自己定義
			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);

			stringEncryptor = encryptor;
		}
		return stringEncryptor;
	}

}

執行main方法打印:

【123456】被加密成【AAM7i7RkQeSDOf1iiAbYIDlfAGbJNch3jVu9KNqPLlwlHS4LFO3Sx22bTipeay5h】
【AAM7i7RkQeSDOf1iiAbYIDlfAGbJNch3jVu9KNqPLlwlHS4LFO3Sx22bTipeay5h】被解密成【123456】
注意,一個同樣的密碼和祕鑰,每次執行加密,密文都是不一樣的。但是解密是沒問題的。

controller執行:

package com.example.gate.controller;


import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.Map;

import org.jasypt.encryption.StringEncryptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

/**
 * jasypt測試
 * 
 * @author lsy
 *
 */
@RestController
@RequestMapping("/jasypt")
public class PrintPassInYmlController {

	@Value("${spring.cloud.client.ip-address}")
	private String ip;
	
	@Value("${spring.application.name}")
	private String servername;
	
	@Value("${server.port}")
	private String port;
	
	
	@Autowired
	StringEncryptor stringEncryptor;
	
	@Value("${mypass.pass1}")
	private String pass1;//yml中定義的是密文
	
	
	//查看程序跑起來後,yml中的密碼是否是明文
	@RequestMapping(value = "/viewPass1",method = RequestMethod.GET)
    @ResponseBody
    public String viewPass1(){
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String dateStr=LocalDateTime.now().format(df);
        
        String mess="viewPass ! 查看mypass.pass1的值是["+pass1+"]。response form  ["+servername+":"+ip+":"+port+"]"+"..."+dateStr;
        return mess;
        
    }
	
	/**
	 * 用jasypt把一個密碼加密(祕鑰用yml中定義的)
	 * @param param
	 * @return
	 */
	@RequestMapping(value = "/jasyptEncode",method = RequestMethod.GET)
    @ResponseBody
    public String jasyptEncode(@RequestParam(required=false) String param){
		System.out.println("jasyptEncode接收請求參數爲==="+param); 
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String dateStr=LocalDateTime.now().format(df);
        
        String newpass=stringEncryptor.encrypt(param);
        String mess="jasyptEncode ! 把["+param+"] 加密成["+newpass+"]。response form  ["+servername+":"+ip+":"+port+"]"+"..."+dateStr;
        return mess;
        
    }
	
	
	/**
	 * 用jasypt把一個密文解密,參數是密文,返回解密後的明文(使用的祕鑰還是yml中定義的)
	 * 
	 * 使用post請求是因爲密碼有特殊字符,所以用post請求體傳值
	 * 
	 * @param param
	 * @return
	 */
	@RequestMapping(value = "/jasyptDecode",method = RequestMethod.POST)
    @ResponseBody
    public String jasyptDecode(@RequestBody String param){
		System.out.println("jasyptDecode接收請求參數爲==="+param); 
		DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String dateStr=LocalDateTime.now().format(df);
		
        Map hm=new HashMap();
        hm.put("uname", "lsy");
        String realpass=stringEncryptor.decrypt(param);
        hm.put("upass", realpass);
        
        String mess="jasyptDecode ! 把["+param+"] 解密成["+realpass+"]。response form  ["+servername+":"+ip+":"+port+"]"+"..."+dateStr;
		System.out.println(mess);
		
        return "jasyptDecode response==="+hm.toString();
    }
	
}

應用跑起來後,查看yml中mypass.pass1的值:

 

我加密一個密碼:

爲了驗證解密,我把上面的密文再發到解密的請求中:

 

注意header的Content-Type要用text/plain

 

這幾種方式都能獲取密文,然後我們就配置到yml中就可以了。

另外說一下ENC()這個標識是可以改的,比如我先改成ENC@[],只要按以下設置即可。其他的基本上就用默認的就行。

#jasypt加密配置
jasypt:
  encryptor:
    password: miyao
    algorithm: PBEWITHHMACSHA512ANDAES_256
    property:
      prefix: "ENC@["
      suffix: "]"

 

另一個需要關心的就是祕鑰的存放了。祕鑰是個字符串,寫在配置文件或者寫在代碼都可以。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章