微服務(wù)SpringBoot整合Jasypt加密工具的場景分析
一、Jasypt介紹
Jasypt是Java加密工具包,能支持對密碼的哈希加密,對文本和二進制數(shù)據(jù)的對稱加解密,還能集成SpringBoot項目對配置文件中的密鑰進行加密存儲。
引入依賴如下:
<!-- 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ù)的安全性。當用戶再次登錄的時候,我們需要將登錄密碼和注冊時保存的密文密碼進行比對,只有比對一致才能完成登錄。
密碼加密工具類主要有三個,它們都是實現(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"; } }
啟動項目后,我們首先注冊用戶密碼localhost:8080/signup/123456
,就能得到密文5b32ygn5pbBvphjIKco6X8Z2VfWqwEUw
,并將其保存到類變量中暫存,當我們再次登錄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 : 用戶登錄失?。?/p>
那么這種加密方式是什么呢?我們可以打開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
主要有如下三個實現(xiàn)類:
BasicPasswordEncryptor
,使用MD5算法;StrongPasswordEncryptor
,使用SHA-256算法;ConfigurablePasswordEncryptor
,可自定義指定哈希算法;
哈希算法是不可逆的,因此只有加密encryptPassword和檢查checkPassword兩個方法。
2.2 文本加密場景
用戶的手機號、身份證號等敏感信息在存儲的時候需要進行加密,但是這些敏感數(shù)據(jù)在需要使用的時候是需要明文解密的,因此不適合使用2.1節(jié)的哈希算法,而是使用對稱加密的形式。
文本加密工具類主要有三個,它們都是實現(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; } }
項目啟動后,我們分別訪問localhost:8080/encryptText/hello
進行加密,訪問localhost:8080/decryptText
進行解密。
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ù)進行加密,就可以分別使用IntegerNumberEncryptor
接口和DecimalNumberEncryptor
接口的實現(xiàn)類。同樣的,這種場景的加密也都是對稱加密,用法完全一樣。
IntegerNumberEncryptor:主要用來對整數(shù)進行加解密。
- BasicIntegerNumberEncryptor
- Algorithm: PBEWithMD5AndDES.
- Key obtention iterations: 1000.
- StrongIntegerNumberEncryptor
- Algorithm: PBEWithMD5AndTripleDES.
- Key obtention iterations: 1000.
- AES256IntegerNumberEncryptor
- Algorithm: PBEWithHMACSHA512AndAES_256.
- Key obtention iterations: 1000.
DecimalNumberEncryptor:主要用來對小數(shù)進行加解密。
- BasicDecimalNumberEncryptor
- Algorithm: PBEWithMD5AndDES.
- Key obtention iterations: 1000.
- StrongDecimalNumberEncryptor
- Algorithm: PBEWithMD5AndTripleDES.
- Key obtention iterations: 1000.
- AES256DecimalNumberEncryptor
- Algorithm: PBEWithHMACSHA512AndAES_256.
- Key obtention iterations: 1000.
2.4 二進制數(shù)據(jù)加密場景
暫未遇到需要加密二進制數(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()進行包裹 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ù)庫密碼進行加密存儲,密文是怎么的來的?可以寫一個測試類,使用第二節(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)造方法,防止被意外實例化 */ 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)過如上的配置,啟動項目,如下從數(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實現(xiàn)配置加密的步驟詳解
- Springboot集成Jasypt實現(xiàn)配置文件加密的方法
- SpringBoot整合jasypt實現(xiàn)敏感信息的加密詳解
- SpringBoot集成Jasypt敏感信息加密的操作方法
- springboot 項目使用jasypt加密數(shù)據(jù)源的方法
- Jasypt對SpringBoot配置文件加密
- jasypt 集成SpringBoot 數(shù)據(jù)庫密碼加密操作
- SpringBoot 集成 Jasypt 對數(shù)據(jù)庫加密以及踩坑的記錄分享
- 基于Jasypt對SpringBoot配置文件加密
- 在SpringBoot中通過jasypt進行加密解密的方法
- SpringBoot使用Jasypt對配置文件和數(shù)據(jù)庫密碼加密
相關(guān)文章
基于JAVA代碼 獲取手機基本信息(本機號碼,SDK版本,系統(tǒng)版本,手機型號)
本文給大家介紹基于java代碼獲取手機基本信息,包括獲取電話管理對象、獲取手機號碼、獲取手機型號、獲取SDK版本、獲取系統(tǒng)版本等相關(guān)信息,對本文感興趣的朋友一起學(xué)習(xí)吧2015-12-12Java分布式鎖、分布式ID和分布式事務(wù)的實現(xiàn)方案
在分布式系統(tǒng)中,分布式鎖、分布式ID和分布式事務(wù)是常用的組件,用于解決并發(fā)控制、唯一標識和數(shù)據(jù)一致性的問題,本文將介紹Java中常用的分布式鎖、分布式ID和分布式事務(wù)的實現(xiàn)方案,并通過具體的示例代碼演示它們的用法和應(yīng)用場景2023-06-06IntelliJ IDEA 2021.1 推出語音、視頻功能,邊寫代碼邊聊天(功能超級強大
這篇文章主要介紹了IntelliJ IDEA 2021.1 推出語音、視頻功能,邊寫代碼邊聊天(功能超級強大),本文通過圖文并茂的形式給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-04-04詳解JAVA使用Comparator接口實現(xiàn)自定義排序
這篇文章主要介紹了JAVA使用Comparator接口實現(xiàn)自定義排序,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-03-03