Spring Boot 安全 API 構(gòu)建之加密解密功能的實(shí)踐記錄
一、描述
在當(dāng)前的數(shù)字化時(shí)代背景下,數(shù)據(jù)安全已成為企業(yè)絕不可忽視的關(guān)鍵領(lǐng)域。為了確保數(shù)據(jù)傳輸?shù)睦喂贪踩裕瑢?duì)API接口實(shí)施加密處理成為了必不可少的一環(huán)。本文將闡述如何在Spring Boot 3.3環(huán)境中迅速落實(shí)API加密的最佳方案,具體采用RSA非對(duì)稱加密算法進(jìn)行說明。
1、選擇合適的加密算法
- 對(duì)稱加密:如 AES(Advanced Encryption Standard),適用于大量數(shù)據(jù)的快速加密和解密,但需要安全地管理密鑰。
- 非對(duì)稱加密:如 RSA(Rivest-Shamir-Adleman),使用公鑰和私鑰對(duì),公鑰用于加密,私鑰用于解密,適合加密少量數(shù)據(jù)和密鑰交換。
2、密鑰管理
- 生成強(qiáng)密鑰:使用安全的隨機(jī)數(shù)生成器來生成密鑰,確保密鑰的隨機(jī)性和強(qiáng)度。
- 安全存儲(chǔ):將密鑰存儲(chǔ)在安全的地方,如密鑰管理系統(tǒng)或加密的配置文件中。避免將密鑰硬編碼在代碼中。
- 密鑰更新:定期更新密鑰,以降低密鑰被破解的風(fēng)險(xiǎn)。
3、數(shù)據(jù)加密
- 對(duì)敏感數(shù)據(jù)加密:如用戶密碼、個(gè)人信息等,在存儲(chǔ)和傳輸過程中進(jìn)行加密。
- 端到端加密:如果可能,實(shí)現(xiàn)端到端加密,確保數(shù)據(jù)在整個(gè)傳輸過程中都是加密的,只有發(fā)送方和接收方能夠解密。
- 加密傳輸:使用 HTTPS 確保數(shù)據(jù)在網(wǎng)絡(luò)傳輸過程中的安全。Spring Boot 3 可以很容易地配置 HTTPS。
4、防止加密漏洞
- 避免弱加密算法:不要使用已被破解或不安全的加密算法。
- 防止加密錯(cuò)誤配置:仔細(xì)配置加密庫和框架,避免錯(cuò)誤的配置導(dǎo)致安全漏洞。
- 輸入驗(yàn)證:對(duì)加密輸入進(jìn)行嚴(yán)格的驗(yàn)證,防止惡意輸入導(dǎo)致加密失敗或安全漏洞。
5、安全日志記錄
- 記錄加密相關(guān)事件:如密鑰生成、加密和解密操作等,以便進(jìn)行審計(jì)和故障排除。
- 保護(hù)日志安全:確保日志文件的安全存儲(chǔ),防止敏感信息泄露。
6、測試和監(jiān)控
- 安全測試:進(jìn)行安全測試,包括加密功能的測試,以確保加密的正確性和安全性。
- 監(jiān)控異常:監(jiān)控加密相關(guān)的異常情況,如加密失敗、密鑰泄露等,并及時(shí)采取措施。
二、RSA加密解密實(shí)現(xiàn)步驟
第一種寫法
1. 配置Spring Boot的依賴
以下是一個(gè)基本的pom.xml文件:
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spring-boot-rsa</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-rsa</name> <description>Demo project for Spring Boot RSA encryption and decryption</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 其他依賴項(xiàng)可以根據(jù)需要添加 --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2. 配置RSA密鑰
首先,在application.yml
文件中配置RSA公鑰和私鑰。注意,由于密鑰可能很長,你可能需要適當(dāng)?shù)負(fù)Q行或使用YAML的多行字符串語法。
rsa: open: true # 是否開啟加密 showLog: true # 是否打印加解密日志 publicKey: '你的RSA公鑰' # RSA公鑰,軟件生成 privateKey: '你的RSA私鑰' # RSA私鑰,軟件生成
注意:在實(shí)際應(yīng)用中,請(qǐng)不要將密鑰硬編碼在配置文件中,特別是私鑰。應(yīng)該使用更安全的方式來管理密鑰,比如環(huán)境變量、密鑰管理服務(wù)(KMS)或安全的配置文件存儲(chǔ)。
3. 讀取配置并初始化密鑰
接下來,在Spring Boot應(yīng)用中讀取這些配置,并初始化RSA密鑰。
import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; @Configuration public class RsaConfig { @Value("${rsa.publicKey}") private String publicKey; @Value("${rsa.privateKey}") private String privateKey; @Bean public PublicKey rsaPublicKey() throws Exception { byte[] keyBytes = Base64.getDecoder().decode(publicKey.getBytes()); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePublic(spec); } @Bean public PrivateKey rsaPrivateKey() throws Exception { byte[] keyBytes = Base64.getDecoder().decode(privateKey.getBytes()); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory kf = KeyFactory.getInstance("RSA"); return kf.generatePrivate(spec); } }
4. 使用RSA密鑰進(jìn)行加密和解密
現(xiàn)在,你可以在服務(wù)類中使用這些密鑰進(jìn)行加密和解密操作。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.crypto.Cipher; import java.security.PrivateKey; import java.security.PublicKey; import java.util.Base64; @Service public class RsaService { private final PublicKey publicKey; private final PrivateKey privateKey; @Autowired public RsaService(PublicKey publicKey, PrivateKey privateKey) { this.publicKey = publicKey; this.privateKey = privateKey; } public String encrypt(String data) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = cipher.doFinal(data.getBytes()); return Base64.getEncoder().encodeToString(encryptedBytes); } public String decrypt(String encryptedData) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData)); return new String(decryptedBytes); } }
5. 測試加密和解密
最后,你可以編寫一個(gè)簡單的控制器或測試類來驗(yàn)證加密和解密功能是否正常工作。
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; @RestController public class RsaController { private final RsaService rsaService; @Autowired public RsaController(RsaService rsaService) { this.rsaService = rsaService; } @GetMapping("/encrypt") public String encrypt(@RequestParam String data) throws Exception { return rsaService.encrypt(data); } @GetMapping("/decrypt") public String decrypt(@RequestParam String encryptedData) throws Exception { return rsaService.decrypt(encryptedData); } }
現(xiàn)在,你可以啟動(dòng)Spring Boot應(yīng)用,并通過訪問/encrypt
和/decrypt
端點(diǎn)來測試RSA加密和解密功能。請(qǐng)確保在測試過程中使用合適的密鑰對(duì),并且不要在生產(chǎn)環(huán)境中暴露私鑰。
第二種寫法
1、創(chuàng)建RSA工具類
創(chuàng)建一個(gè)RSA工具類來處理加密和解密操作。這個(gè)類將包含生成密鑰對(duì)、加密和解密的方法。
package com.example.springbootrsa.util; import javax.crypto.Cipher; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.X509EncodedKeySpec; import java.util.Base64; public class RSAUtil { // 生成密鑰對(duì) public static KeyPair generateKeyPair() throws Exception { KeyPairGenerator keyGen = KeyPairGenerator.getInstance("RSA"); keyGen.initialize(2048); return keyGen.generateKeyPair(); } // 公鑰加密 public static String encrypt(String data, PublicKey publicKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.ENCRYPT_MODE, publicKey); byte[] encryptedBytes = cipher.doFinal(data.getBytes("UTF-8")); return Base64.getEncoder().encodeToString(encryptedBytes); } // 私鑰解密 public static String decrypt(String encryptedData, PrivateKey privateKey) throws Exception { Cipher cipher = Cipher.getInstance("RSA"); cipher.init(Cipher.DECRYPT_MODE, privateKey); byte[] decryptedBytes = cipher.doFinal(Base64.getDecoder().decode(encryptedData)); return new String(decryptedBytes, "UTF-8"); } // 公鑰字符串表示 public static String getPublicKeyString(PublicKey publicKey) { return Base64.getEncoder().encodeToString(publicKey.getEncoded()); } // 私鑰字符串表示 public static String getPrivateKeyString(PrivateKey privateKey) { return Base64.getEncoder().encodeToString(privateKey.getEncoded()); } // 從字符串重建公鑰 public static PublicKey getPublicKeyFromString(String key) throws Exception { byte[] keyBytes = Base64.getDecoder().decode(key); X509EncodedKeySpec spec = new X509EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePublic(spec); } // 從字符串重建私鑰 public static PrivateKey getPrivateKeyFromString(String key) throws Exception { byte[] keyBytes = Base64.getDecoder().decode(key); PKCS8EncodedKeySpec spec = new PKCS8EncodedKeySpec(keyBytes); KeyFactory keyFactory = KeyFactory.getInstance("RSA"); return keyFactory.generatePrivate(spec); } }
2、創(chuàng)建Spring Boot控制器
創(chuàng)建一個(gè)簡單的Spring Boot控制器來演示如何使用RSA加密和解密
package com.example.springbootrsa.controller; import com.example.springbootrsa.util.RSAUtil; import org.springframework.web.bind.annotation.*; import java.security.KeyPair; @RestController @RequestMapping("/api") public class RSAController { private KeyPair keyPair; public RSAController() throws Exception { this.keyPair = RSAUtil.generateKeyPair(); } @GetMapping("/encrypt") public String encrypt(@RequestParam String data) throws Exception { return RSAUtil.encrypt(data, keyPair.getPublic()); } @GetMapping("/decrypt") public String decrypt(@RequestParam String encryptedData) throws Exception { return RSAUtil.decrypt(encryptedData, keyPair.getPrivate()); } @GetMapping("/publicKey") public String getPublicKey() { try { return RSAUtil.getPublicKeyString(keyPair.getPublic()); } catch (Exception e) { e.printStackTrace(); return null; } } @GetMapping("/privateKey") public String getPrivateKey() { try { return RSAUtil.getPrivateKeyString(keyPair.getPrivate()); } catch (Exception e) { e.printStackTrace(); return null; } } }
3、測試RSA加密和解密
現(xiàn)在,您可以運(yùn)行Spring Boot應(yīng)用程序,并通過訪問以下端點(diǎn)來測試RSA加密和解密:
- 獲取公鑰:
GET /api/publicKey
- 獲取私鑰:
GET /api/privateKey
(請(qǐng)注意,在生產(chǎn)環(huán)境中,私鑰應(yīng)該保密) - 加密數(shù)據(jù):
GET /api/encrypt?data=yourData
- 解密數(shù)據(jù):
GET /api/decrypt?encryptedData=yourEncryptedData
三、AES加密解密實(shí)現(xiàn)步驟
1. 創(chuàng)建Spring Boot項(xiàng)目
你可以使用Spring Initializr創(chuàng)建一個(gè)新的Spring Boot項(xiàng)目,選擇以下依賴項(xiàng):
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.example</groupId> <artifactId>spring-boot-rsa</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>spring-boot-rsa</name> <description>Demo project for Spring Boot RSA encryption and decryption</description> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>3.0.0</version> <relativePath/> <!-- lookup parent from repository --> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <!-- 其他依賴項(xiàng)可以根據(jù)需要添加 --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2. 添加AES加密解密工具類
首先,我們需要一個(gè)工具類來處理AES加密和解密操作。
package com.example.demo.util; import javax.crypto.Cipher; import javax.crypto.KeyGenerator; import javax.crypto.SecretKey; import javax.crypto.spec.SecretKeySpec; import java.util.Base64; public class AESUtil { // 生成AES密鑰 public static SecretKey generateKey(int n) throws Exception { KeyGenerator keyGenerator = KeyGenerator.getInstance("AES"); keyGenerator.init(n); SecretKey secretKey = keyGenerator.generateKey(); return secretKey; } // 將密鑰轉(zhuǎn)換為字符串 public static String encodeKey(SecretKey key) { return Base64.getEncoder().encodeToString(key.getEncoded()); } // 將字符串轉(zhuǎn)換為密鑰 public static SecretKey decodeKey(String encodedKey) { byte[] decodedKey = Base64.getDecoder().decode(encodedKey); return new SecretKeySpec(decodedKey, 0, decodedKey.length, "AES"); } // 加密 public static String encrypt(String data, SecretKey key) throws Exception { Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.ENCRYPT_MODE, key); byte[] encryptedData = cipher.doFinal(data.getBytes("UTF-8")); return Base64.getEncoder().encodeToString(encryptedData); } // 解密 public static String decrypt(String encryptedData, SecretKey key) throws Exception { Cipher cipher = Cipher.getInstance("AES"); cipher.init(Cipher.DECRYPT_MODE, key); byte[] decodedData = Base64.getDecoder().decode(encryptedData); byte[] decryptedData = cipher.doFinal(decodedData); return new String(decryptedData, "UTF-8"); } }
3. 創(chuàng)建控制器來處理加密和解密請(qǐng)求
接下來,我們創(chuàng)建一個(gè)Spring Boot控制器來處理加密和解密請(qǐng)求。
package com.example.demo.controller; import com.example.demo.util.AESUtil; import org.springframework.web.bind.annotation.*; import javax.crypto.SecretKey; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/api") public class AESController { // 用于存儲(chǔ)密鑰的變量(在實(shí)際應(yīng)用中,密鑰應(yīng)該安全存儲(chǔ)) private static SecretKey secretKey; static { try { secretKey = AESUtil.generateKey(256); // 256位AES密鑰 } catch (Exception e) { e.printStackTrace(); } } @GetMapping("/encrypt") public Map<String, String> encrypt(@RequestParam String data) { Map<String, String> response = new HashMap<>(); try { String encryptedData = AESUtil.encrypt(data, secretKey); response.put("encryptedData", encryptedData); } catch (Exception e) { response.put("error", e.getMessage()); } return response; } @GetMapping("/decrypt") public Map<String, String> decrypt(@RequestParam String encryptedData) { Map<String, String> response = new HashMap<>(); try { String decryptedData = AESUtil.decrypt(encryptedData, secretKey); response.put("decryptedData", decryptedData); } catch (Exception e) { response.put("error", e.getMessage()); } return response; } @GetMapping("/key") public Map<String, String> getKey() { Map<String, String> response = new HashMap<>(); try { String encodedKey = AESUtil.encodeKey(secretKey); response.put("encodedKey", encodedKey); } catch (Exception e) { response.put("error", e.getMessage()); } return response; } }
4. 啟動(dòng)Spring Boot應(yīng)用程序
確保你的application.properties
或application.yml
文件配置正確,然后運(yùn)行Spring Boot應(yīng)用程序。
5. 測試API
你可以使用瀏覽器或工具(如Postman)來測試這些API。
- 獲取密鑰:GET http://localhost:8080/api/key
- 加密數(shù)據(jù):GET http://localhost:8080/api/encrypt?data=HelloWorld
- 解密數(shù)據(jù):GET http://localhost:8080/api/decrypt?encryptedData=<Base64EncodedEncryptedData>
注意事項(xiàng)
- 密鑰管理:在實(shí)際應(yīng)用中,密鑰應(yīng)該安全存儲(chǔ)和管理,不要硬編碼在代碼中。
- 異常處理:在生產(chǎn)代碼中,應(yīng)該有更完善的異常處理機(jī)制。
- HTTPS:確保你的API通過HTTPS進(jìn)行通信,以保護(hù)傳輸中的數(shù)據(jù)。
到此這篇關(guān)于Spring Boot 安全 API 構(gòu)建:加密解密功能的卓越實(shí)踐的文章就介紹到這了,更多相關(guān)Spring Boot API 加密解密內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot 如何重定向redirect 并隱藏參數(shù)
這篇文章主要介紹了springboot 如何重定向redirect 并隱藏參數(shù)的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09java 數(shù)值類型分秒時(shí)間格式化的實(shí)例代碼
這篇文章主要介紹了java 數(shù)值類型分秒時(shí)間格式化的實(shí)例代碼的相關(guān)資料,將秒或分鐘的值轉(zhuǎn)換為xx天xx小時(shí)xx分鐘xx秒 如果 “xx” 為0 自動(dòng)缺省,需要的朋友可以參考下2017-07-07Spring BeanFactory和FactoryBean有哪些區(qū)別
這篇文章主要介紹了Spring BeanFactory 與 FactoryBean 的區(qū)別詳情,BeanFactory 和 FactoryBean 的區(qū)別卻是一個(gè)很重要的知識(shí)點(diǎn),在本文中將結(jié)合源碼進(jìn)行分析講解,需要的小伙伴可以參考一下2023-02-02Spring使用Configuration注解管理bean的方式詳解
在Spring的世界里,Configuration注解就像是一位細(xì)心的園丁,它的主要職責(zé)是在這個(gè)繁花似錦的園子里,幫助我們聲明和管理各種各樣的bean,本文給大家介紹了在Spring中如何優(yōu)雅地管理你的bean,需要的朋友可以參考下2024-05-05細(xì)致解讀希爾排序算法與相關(guān)的Java代碼實(shí)現(xiàn)
這篇文章主要介紹了希爾排序算法與相關(guān)的Java代碼實(shí)現(xiàn),希爾排序的時(shí)間復(fù)雜度根據(jù)步長序列的不同而不同,需要的朋友可以參考下2016-05-05Java中synchronized實(shí)現(xiàn)原理詳解
這篇文章主要介紹了Java中synchronized實(shí)現(xiàn)原理詳解,涉及synchronized實(shí)現(xiàn)同步的基礎(chǔ),Java對(duì)象頭,Monitor,Mark Word,鎖優(yōu)化,自旋鎖等相關(guān)內(nèi)容,具有一定借鑒價(jià)值,需要的朋友可以參考下。2017-11-11關(guān)于Filter中獲取請(qǐng)求體body后再次讀取的問題
這篇文章主要介紹了關(guān)于Filter中獲取請(qǐng)求體body后再次讀取的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-03-03