微服務(wù)SpringBoot整合Jasypt加密工具的場景分析
一、Jasypt介紹
Jasypt是Java加密工具包,能支持對密碼的哈希加密,對文本和二進(jìn)制數(shù)據(jù)的對稱加解密,還能集成SpringBoot項(xiàng)目對配置文件中的密鑰進(jìn)行加密存儲。
引入依賴如下:
<!-- https://mvnrepository.com/artifact/com.github.ulisesbocchio/jasypt-spring-boot-starter -->
<dependency>
<groupId>com.github.ulisesbocchio</groupId>
<artifactId>jasypt-spring-boot-starter</artifactId>
<version>3.0.4</version>
</dependency>
二、Jasypt手動使用
2.1 密碼加密場景
用戶注冊賬戶的時候需要輸入密碼,我們將密碼加密后保存到數(shù)據(jù)庫中,保證用戶的敏感數(shù)據(jù)的安全性。當(dāng)用戶再次登錄的時候,我們需要將登錄密碼和注冊時保存的密文密碼進(jìn)行比對,只有比對一致才能完成登錄。
密碼加密工具類主要有三個,它們都是實(shí)現(xiàn)了PasswordEncryptor接口,下面我們逐步來看。
@Slf4j
@RestController
public class SignController {
private final BasicPasswordEncryptor basicPasswordEncryptor = new BasicPasswordEncryptor();
private String encryptedPassword = null;
@GetMapping("/signup/{password}")
public String signup(@PathVariable String password){
log.info("用戶注冊密碼為:{}", password);
encryptedPassword = basicPasswordEncryptor.encryptPassword(password);
log.info("用戶注冊密碼加密后為:{}", encryptedPassword);
return encryptedPassword;
}
@GetMapping("/signin/{password}")
public String signin(@PathVariable String password){
log.info("用戶登錄密碼為:{}", password);
if(basicPasswordEncryptor.checkPassword(password, encryptedPassword)){
log.info("用戶登錄成功!");
return "success";
}
log.info("用戶登錄失??!");
return "fail";
}
}
啟動項(xiàng)目后,我們首先注冊用戶密碼localhost:8080/signup/123456,就能得到密文5b32ygn5pbBvphjIKco6X8Z2VfWqwEUw,并將其保存到類變量中暫存,當(dāng)我們再次登錄localhost:8080/signin/123456,就能登錄成功了。相反的,如果登錄時密碼隨意輸錯,就會登錄失敗。
2022-10-11 15:41:57.038 INFO 26268 --- [nio-8080-exec-1] c.e.myapp.controller.SignController : 用戶注冊密碼為:123456
2022-10-11 15:41:57.039 INFO 26268 --- [nio-8080-exec-1] c.e.myapp.controller.SignController : 用戶注冊密碼加密后為:5b32ygn5pbBvphjIKco6X8Z2VfWqwEUw
2022-10-11 15:42:07.405 INFO 26268 --- [nio-8080-exec-3] c.e.myapp.controller.SignController : 用戶登錄密碼為:123456
2022-10-11 15:42:07.406 INFO 26268 --- [nio-8080-exec-3] c.e.myapp.controller.SignController : 用戶登錄成功!
2022-10-11 15:42:12.767 INFO 26268 --- [nio-8080-exec-4] c.e.myapp.controller.SignController : 用戶登錄密碼為:123457
2022-10-11 15:42:12.767 INFO 26268 --- [nio-8080-exec-4] c.e.myapp.controller.SignController : 用戶登錄失??!
那么這種加密方式是什么呢?我們可以打開BasicPasswordEncryptor的源碼,看到類上面的注釋:
- Algorithm: MD5.
- Salt size: 8 bytes.
- Iterations: 1000.
意思就是使用的MD5這種哈希算法,并且使用8字節(jié)(64位)的鹽值,迭代計算1000次得到的密文。
除了使用如上的BasicPasswordEncryptor工具之外,還有StrongPasswordEncryptor工具類,它的加密登記更加的安全:
- Algorithm: SHA-256.
- Salt size: 16 bytes.
- Iterations: 100000.
如果這些加密算法都不能滿足你的要求,就可以使用ConfigurablePasswordEncryptor來自定義加密工具類ConfigurablePasswordEncryptor,可以設(shè)置自己需要使用的算法。
總結(jié):
接口類PasswordEncryptor主要有如下三個實(shí)現(xiàn)類:
BasicPasswordEncryptor,使用MD5算法;StrongPasswordEncryptor,使用SHA-256算法;ConfigurablePasswordEncryptor,可自定義指定哈希算法;
哈希算法是不可逆的,因此只有加密encryptPassword和檢查checkPassword兩個方法。
2.2 文本加密場景
用戶的手機(jī)號、身份證號等敏感信息在存儲的時候需要進(jìn)行加密,但是這些敏感數(shù)據(jù)在需要使用的時候是需要明文解密的,因此不適合使用2.1節(jié)的哈希算法,而是使用對稱加密的形式。
文本加密工具類主要有三個,它們都是實(shí)現(xiàn)了TextEncryptor接口,下面我們逐步來看。
@Slf4j
@RestController
public class TextController {
private static final BasicTextEncryptor basicTextEncryptor = new BasicTextEncryptor();
private static final String SECRET = "hello";
private String encryptedText = null;
static {
basicTextEncryptor.setPassword(SECRET);
}
@GetMapping("/encryptText/{plainText}")
public String encryptText(@PathVariable String plainText){
log.info("用戶輸入明文:{}", plainText);
encryptedText = basicTextEncryptor.encrypt(plainText);
log.info("用戶加密密文:{}", encryptedText);
return encryptedText;
}
@GetMapping("/decryptText")
public String decryptText(){
String plainText = basicTextEncryptor.decrypt(encryptedText);
log.info("用戶原始明文:{}", plainText);
return plainText;
}
}
項(xiàng)目啟動后,我們分別訪問localhost:8080/encryptText/hello進(jìn)行加密,訪問localhost:8080/decryptText進(jìn)行解密。
2022-10-11 15:52:36.949 INFO 21652 --- [nio-8080-exec-1] c.e.myapp.controller.TextController : 用戶輸入明文:hello
2022-10-11 15:52:36.950 INFO 21652 --- [nio-8080-exec-1] c.e.myapp.controller.TextController : 用戶加密密文:u/qYluhyFpyOA6xMD3z3JA==
2022-10-11 15:52:46.345 INFO 21652 --- [nio-8080-exec-2] c.e.myapp.controller.TextController : 用戶原始明文:hello
我們同樣打開BasicTextEncryptor可以看到它的加密原理:
- Algorithm: PBEWithMD5AndDES.
- Key obtention iterations: 1000.
同樣的,我們可以使用安全性更高的StrongTextEncryptor:
- Algorithm: PBEWithMD5AndTripleDES.
- Key obtention iterations: 1000.
還有安全性更高的AES256TextEncryptor:
- Algorithm: PBEWithHMACSHA512AndAES_256".
- Key obtention iterations: 1000.
2.3 數(shù)值加密場景
如果需要對整數(shù)或者小數(shù)進(jìn)行加密,就可以分別使用IntegerNumberEncryptor接口和DecimalNumberEncryptor接口的實(shí)現(xiàn)類。同樣的,這種場景的加密也都是對稱加密,用法完全一樣。
IntegerNumberEncryptor:主要用來對整數(shù)進(jìn)行加解密。
- BasicIntegerNumberEncryptor
- Algorithm: PBEWithMD5AndDES.
- Key obtention iterations: 1000.
- StrongIntegerNumberEncryptor
- Algorithm: PBEWithMD5AndTripleDES.
- Key obtention iterations: 1000.
- AES256IntegerNumberEncryptor
- Algorithm: PBEWithHMACSHA512AndAES_256.
- Key obtention iterations: 1000.
DecimalNumberEncryptor:主要用來對小數(shù)進(jìn)行加解密。
- BasicDecimalNumberEncryptor
- Algorithm: PBEWithMD5AndDES.
- Key obtention iterations: 1000.
- StrongDecimalNumberEncryptor
- Algorithm: PBEWithMD5AndTripleDES.
- Key obtention iterations: 1000.
- AES256DecimalNumberEncryptor
- Algorithm: PBEWithHMACSHA512AndAES_256.
- Key obtention iterations: 1000.
2.4 二進(jìn)制數(shù)據(jù)加密場景
暫未遇到需要加密二進(jìn)制數(shù)據(jù)的業(yè)務(wù)場景,此處略過,使用方法可以參考官網(wǎng)。
三、Jasypt整合SpringBoot
SpringBoot應(yīng)用中有很多密鑰和密碼都是存儲在配置文件中的,我們需要將它們以密文的方式存儲起來。
# 服務(wù)器配置
server:
port: 8080
# Spring配置
spring:
# 數(shù)據(jù)源配置
datasource:
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/test?characterEncoding=utf-8&&serverTimezone=Asia/Shanghai&&useSSL=false
username: root
# 此處是密碼的密文,要用ENC()進(jìn)行包裹
password: ENC(KZeGx0ixuy4UrBp1HuhiDNnKB0cJr0cW)
# mybatis配置
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
# 加密配置
jasypt:
encryptor:
# 指定加密密鑰,生產(chǎn)環(huán)境請放到啟動參數(shù)里面
password: your-secret
# 指定解密算法,需要和加密時使用的算法一致
algorithm: PBEWithMD5AndDES
# 指定initialization vector類型
iv-generator-classname: org.jasypt.iv.NoIvGenerator
如上是對數(shù)據(jù)庫密碼進(jìn)行加密存儲,密文是怎么的來的?可以寫一個測試類,使用第二節(jié)介紹的內(nèi)容自己手動加密。
@Slf4j
public final class JasyptUtils {
/**
* 加密使用密鑰
*/
private static final String PRIVATE_KEY = "lybgeek";
private static BasicTextEncryptor basicTextEncryptor = new BasicTextEncryptor();
static {
basicTextEncryptor.setPassword(PRIVATE_KEY);
}
/**
* 私有構(gòu)造方法,防止被意外實(shí)例化
*/
private JasyptUtils() {
}
/**
* 明文加密
*
* @param plaintext 明文
* @return String
*/
public static String encrypt(String plaintext) {
log.info("明文字符串為:{}", plaintext);
// 使用的加密算法參考2.2節(jié)內(nèi)容,也可以在源碼的類注釋中看到
String ciphertext = basicTextEncryptor.encrypt(plaintext);
log.info("密文字符串為:{}", ciphertext);
return ciphertext;
}
/**
* 解密
*
* @param ciphertext 密文
* @return String
*/
public static String decrypt(String ciphertext) {
log.info("密文字符串為:{}", ciphertext);
ciphertext = "ENC(" + ciphertext + ")";
if (PropertyValueEncryptionUtils.isEncryptedValue(ciphertext)) {
String plaintext = PropertyValueEncryptionUtils.decrypt(ciphertext, basicTextEncryptor);
log.info("明文字符串為:{}", plaintext);
return plaintext;
}
log.error("解密失敗!");
return "";
}
}
@Slf4j
public class JasyptUtilsTest {
@Test
public void testEncrypt(){
String plainText = "Glrs@1234";
String ciperText = JasyptUtils.encrypt(plainText);
log.info("加密后的密文為:{}", ciperText);
}
@Test
public void testDecrypt(){
String ciperText = "KZeGx0ixuy4UrBp1HuhiDNnKB0cJr0cW";
String plainText = JasyptUtils.decrypt(ciperText);
log.info("解密后的明文為:{}", plainText);
}
}
經(jīng)過如上的配置,啟動項(xiàng)目,如下從數(shù)據(jù)庫獲取數(shù)據(jù)的應(yīng)用邏輯就能正常使用了。
@Slf4j
@RestController
public class HelloController {
@Autowired
UserMapper userMapper;
@GetMapping("/getHello")
public String getHello(){
log.info("myapp works!");
List<User> users = userMapper.listUsers();
return users.toString();
}
}
@Mapper
public interface UserMapper {
List<User> listUsers();
}
<mapper namespace="com.example.myapp.mapper.UserMapper">
<select id="listUsers" resultType="com.example.myapp.bean.User">
select zu.user_id userId, zu.user_name userName, zu.age age, zu.user_email userEmail from zx_user zu;
</select>
</mapper>
四、生成環(huán)境啟動
生產(chǎn)環(huán)境密鑰作為啟動參數(shù):
java -jar -Djasypt.encryptor.password=your-secret
五、參考文檔
Jasypt: Java simplified encryption - Jasypt: Java simplified encryption - Main
到此這篇關(guān)于微服務(wù)SpringBoot整合Jasypt加密工具的場景分析的文章就介紹到這了,更多相關(guān)SpringBoot整合Jasypt內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- springboot使用jasypt對配置文件加密加密數(shù)據(jù)庫連接的操作代碼
- SpringBoot整合Jasypt實(shí)現(xiàn)配置加密的步驟詳解
- Springboot集成Jasypt實(shí)現(xiàn)配置文件加密的方法
- SpringBoot整合jasypt實(shí)現(xiàn)敏感信息的加密詳解
- SpringBoot集成Jasypt敏感信息加密的操作方法
- springboot 項(xiàng)目使用jasypt加密數(shù)據(jù)源的方法
- Jasypt對SpringBoot配置文件加密
- jasypt 集成SpringBoot 數(shù)據(jù)庫密碼加密操作
- SpringBoot 集成 Jasypt 對數(shù)據(jù)庫加密以及踩坑的記錄分享
- 基于Jasypt對SpringBoot配置文件加密
- 在SpringBoot中通過jasypt進(jìn)行加密解密的方法
- SpringBoot使用Jasypt對配置文件和數(shù)據(jù)庫密碼加密
相關(guān)文章
Spring Boot 部署過程解析(jar or war)
這篇文章主要介紹了Spring Boot 部署過程解析(jar or war),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下2019-09-09
feign調(diào)用第三方接口,編碼定義GBK,響應(yīng)中文亂碼處理方式
這篇文章主要介紹了feign調(diào)用第三方接口,編碼定義GBK,響應(yīng)中文亂碼處理方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
關(guān)于Https協(xié)議和HttpClient的實(shí)現(xiàn)詳解
這篇文章主要給大家介紹了關(guān)于Https協(xié)議和HttpClient實(shí)現(xiàn)的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2018-05-05
SpringBoot 普通類調(diào)用Bean對象的一種方式推薦
這篇文章主要介紹了SpringBoot 普通類調(diào)用Bean對象的一種方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11

