Spring Boot 安全 API 構建之加密解密功能的實踐記錄
一、描述
在當前的數(shù)字化時代背景下,數(shù)據(jù)安全已成為企業(yè)絕不可忽視的關鍵領域。為了確保數(shù)據(jù)傳輸?shù)睦喂贪踩裕瑢PI接口實施加密處理成為了必不可少的一環(huán)。本文將闡述如何在Spring Boot 3.3環(huán)境中迅速落實API加密的最佳方案,具體采用RSA非對稱加密算法進行說明。
1、選擇合適的加密算法
- 對稱加密:如 AES(Advanced Encryption Standard),適用于大量數(shù)據(jù)的快速加密和解密,但需要安全地管理密鑰。
- 非對稱加密:如 RSA(Rivest-Shamir-Adleman),使用公鑰和私鑰對,公鑰用于加密,私鑰用于解密,適合加密少量數(shù)據(jù)和密鑰交換。
2、密鑰管理
- 生成強密鑰:使用安全的隨機數(shù)生成器來生成密鑰,確保密鑰的隨機性和強度。
- 安全存儲:將密鑰存儲在安全的地方,如密鑰管理系統(tǒng)或加密的配置文件中。避免將密鑰硬編碼在代碼中。
- 密鑰更新:定期更新密鑰,以降低密鑰被破解的風險。
3、數(shù)據(jù)加密
- 對敏感數(shù)據(jù)加密:如用戶密碼、個人信息等,在存儲和傳輸過程中進行加密。
- 端到端加密:如果可能,實現(xiàn)端到端加密,確保數(shù)據(jù)在整個傳輸過程中都是加密的,只有發(fā)送方和接收方能夠解密。
- 加密傳輸:使用 HTTPS 確保數(shù)據(jù)在網(wǎng)絡傳輸過程中的安全。Spring Boot 3 可以很容易地配置 HTTPS。
4、防止加密漏洞
- 避免弱加密算法:不要使用已被破解或不安全的加密算法。
- 防止加密錯誤配置:仔細配置加密庫和框架,避免錯誤的配置導致安全漏洞。
- 輸入驗證:對加密輸入進行嚴格的驗證,防止惡意輸入導致加密失敗或安全漏洞。
5、安全日志記錄
- 記錄加密相關事件:如密鑰生成、加密和解密操作等,以便進行審計和故障排除。
- 保護日志安全:確保日志文件的安全存儲,防止敏感信息泄露。
6、測試和監(jiān)控
- 安全測試:進行安全測試,包括加密功能的測試,以確保加密的正確性和安全性。
- 監(jiān)控異常:監(jiān)控加密相關的異常情況,如加密失敗、密鑰泄露等,并及時采取措施。
二、RSA加密解密實現(xiàn)步驟
第一種寫法
1. 配置Spring Boot的依賴
以下是一個基本的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> <!-- 其他依賴項可以根據(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公鑰和私鑰。注意,由于密鑰可能很長,你可能需要適當?shù)負Q行或使用YAML的多行字符串語法。
rsa: open: true # 是否開啟加密 showLog: true # 是否打印加解密日志 publicKey: '你的RSA公鑰' # RSA公鑰,軟件生成 privateKey: '你的RSA私鑰' # RSA私鑰,軟件生成
注意:在實際應用中,請不要將密鑰硬編碼在配置文件中,特別是私鑰。應該使用更安全的方式來管理密鑰,比如環(huán)境變量、密鑰管理服務(KMS)或安全的配置文件存儲。
3. 讀取配置并初始化密鑰
接下來,在Spring Boot應用中讀取這些配置,并初始化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密鑰進行加密和解密
現(xià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. 測試加密和解密
最后,你可以編寫一個簡單的控制器或測試類來驗證加密和解密功能是否正常工作。
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)在,你可以啟動Spring Boot應用,并通過訪問/encrypt
和/decrypt
端點來測試RSA加密和解密功能。請確保在測試過程中使用合適的密鑰對,并且不要在生產(chǎn)環(huán)境中暴露私鑰。
第二種寫法
1、創(chuàng)建RSA工具類
創(chuàng)建一個RSA工具類來處理加密和解密操作。這個類將包含生成密鑰對、加密和解密的方法。
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 { // 生成密鑰對 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)建一個簡單的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)在,您可以運行Spring Boot應用程序,并通過訪問以下端點來測試RSA加密和解密:
- 獲取公鑰:
GET /api/publicKey
- 獲取私鑰:
GET /api/privateKey
(請注意,在生產(chǎn)環(huán)境中,私鑰應該保密) - 加密數(shù)據(jù):
GET /api/encrypt?data=yourData
- 解密數(shù)據(jù):
GET /api/decrypt?encryptedData=yourEncryptedData
三、AES加密解密實現(xiàn)步驟
1. 創(chuàng)建Spring Boot項目
你可以使用Spring Initializr創(chuàng)建一個新的Spring Boot項目,選擇以下依賴項:
<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> <!-- 其他依賴項可以根據(jù)需要添加 --> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
2. 添加AES加密解密工具類
首先,我們需要一個工具類來處理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; } // 將密鑰轉換為字符串 public static String encodeKey(SecretKey key) { return Base64.getEncoder().encodeToString(key.getEncoded()); } // 將字符串轉換為密鑰 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)建控制器來處理加密和解密請求
接下來,我們創(chuàng)建一個Spring Boot控制器來處理加密和解密請求。
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 { // 用于存儲密鑰的變量(在實際應用中,密鑰應該安全存儲) 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. 啟動Spring Boot應用程序
確保你的application.properties
或application.yml
文件配置正確,然后運行Spring Boot應用程序。
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>
注意事項
- 密鑰管理:在實際應用中,密鑰應該安全存儲和管理,不要硬編碼在代碼中。
- 異常處理:在生產(chǎn)代碼中,應該有更完善的異常處理機制。
- HTTPS:確保你的API通過HTTPS進行通信,以保護傳輸中的數(shù)據(jù)。
到此這篇關于Spring Boot 安全 API 構建:加密解密功能的卓越實踐的文章就介紹到這了,更多相關Spring Boot API 加密解密內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
springboot 如何重定向redirect 并隱藏參數(shù)
這篇文章主要介紹了springboot 如何重定向redirect 并隱藏參數(shù)的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-09-09Spring BeanFactory和FactoryBean有哪些區(qū)別
這篇文章主要介紹了Spring BeanFactory 與 FactoryBean 的區(qū)別詳情,BeanFactory 和 FactoryBean 的區(qū)別卻是一個很重要的知識點,在本文中將結合源碼進行分析講解,需要的小伙伴可以參考一下2023-02-02Spring使用Configuration注解管理bean的方式詳解
在Spring的世界里,Configuration注解就像是一位細心的園丁,它的主要職責是在這個繁花似錦的園子里,幫助我們聲明和管理各種各樣的bean,本文給大家介紹了在Spring中如何優(yōu)雅地管理你的bean,需要的朋友可以參考下2024-05-05