Spring Boot 安全 API 构建之加密解密功能的实践记录

 更新时间:2024年10月31日 14:55:53   作者:Yaml墨韵  
本文详述了如何在SpringBoot3.3环境中实施API加密的最佳实践,包括选择合适的加密算法,密钥管理,数据加密,防止加密漏洞,安全日志记录,测试和监控等方面,同时,文章也对RSA非对称加密和AES对称加密的实现步骤进行了详细的解析

一、描述

在当前的数字化时代背景下,数据安全已成为企业绝不可忽视的关键领域。为了确保数据传输的牢固安全性,对API接口实施加密处理成为了必不可少的一环。本文将阐述如何在Spring Boot 3.3环境中迅速落实API加密的最佳方案,具体采用RSA非对称加密算法进行说明。

1、选择合适的加密算法

  • 对称加密:如 AES(Advanced Encryption Standard),适用于大量数据的快速加密和解密,但需要安全地管理密钥。
  • 非对称加密:如 RSA(Rivest-Shamir-Adleman),使用公钥和私钥对,公钥用于加密,私钥用于解密,适合加密少量数据和密钥交换。

2、密钥管理

  • 生成强密钥:使用安全的随机数生成器来生成密钥,确保密钥的随机性和强度。
  • 安全存储:将密钥存储在安全的地方,如密钥管理系统或加密的配置文件中。避免将密钥硬编码在代码中。
  • 密钥更新:定期更新密钥,以降低密钥被破解的风险。

3、数据加密

  • 对敏感数据加密:如用户密码、个人信息等,在存储和传输过程中进行加密。
  • 端到端加密:如果可能,实现端到端加密,确保数据在整个传输过程中都是加密的,只有发送方和接收方能够解密。
  • 加密传输:使用 HTTPS 确保数据在网络传输过程中的安全。Spring Boot 3 可以很容易地配置 HTTPS。

4、防止加密漏洞

  • 避免弱加密算法:不要使用已被破解或不安全的加密算法。
  • 防止加密错误配置:仔细配置加密库和框架,避免错误的配置导致安全漏洞。
  • 输入验证:对加密输入进行严格的验证,防止恶意输入导致加密失败或安全漏洞。

5、安全日志记录

  • 记录加密相关事件:如密钥生成、加密和解密操作等,以便进行审计和故障排除。
  • 保护日志安全:确保日志文件的安全存储,防止敏感信息泄露。

6、测试和监控

  • 安全测试:进行安全测试,包括加密功能的测试,以确保加密的正确性和安全性。
  • 监控异常:监控加密相关的异常情况,如加密失败、密钥泄露等,并及时采取措施。

二、RSA加密解密实现步骤

第一种写法

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>  
        <!-- 其他依赖项可以根据需要添加 -->  
    </dependencies>  
    <build>  
        <plugins>  
            <plugin>  
                <groupId>org.springframework.boot</groupId>  
                <artifactId>spring-boot-maven-plugin</artifactId>  
            </plugin>  
        </plugins>  
    </build>  
</project>

2. 配置RSA密钥

首先,在application.yml文件中配置RSA公钥和私钥。注意,由于密钥可能很长,你可能需要适当地换行或使用YAML的多行字符串语法。

rsa:  
    open: true          # 是否开启加密 
    showLog: true       # 是否打印加解密日志 
    publicKey: '你的RSA公钥'  # RSA公钥,软件生成 
    privateKey: '你的RSA私钥'  # RSA私钥,软件生成

注意:在实际应用中,请不要将密钥硬编码在配置文件中,特别是私钥。应该使用更安全的方式来管理密钥,比如环境变量、密钥管理服务(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密钥进行加密和解密

现在,你可以在服务类中使用这些密钥进行加密和解密操作。

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);  
    }  
}

现在,你可以启动Spring Boot应用,并通过访问/encrypt/decrypt端点来测试RSA加密和解密功能。请确保在测试过程中使用合适的密钥对,并且不要在生产环境中暴露私钥。

第二种写法

1、创建RSA工具类

创建一个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、创建Spring Boot控制器

创建一个简单的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加密和解密

现在,您可以运行Spring Boot应用程序,并通过访问以下端点来测试RSA加密和解密:

  • 获取公钥GET /api/publicKey
  • 获取私钥GET /api/privateKey(请注意,在生产环境中,私钥应该保密)
  • 加密数据GET /api/encrypt?data=yourData
  • 解密数据GET /api/decrypt?encryptedData=yourEncryptedData

三、AES加密解密实现步骤

1. 创建Spring Boot项目

你可以使用Spring Initializr创建一个新的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>  
        <!-- 其他依赖项可以根据需要添加 -->  
    </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. 创建控制器来处理加密和解密请求

接下来,我们创建一个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.propertiesapplication.yml文件配置正确,然后运行Spring Boot应用程序。

5. 测试API

你可以使用浏览器或工具(如Postman)来测试这些API。

  • 获取密钥:GET http://localhost:8080/api/key
  • 加密数据:GET http://localhost:8080/api/encrypt?data=HelloWorld
  • 解密数据:GET http://localhost:8080/api/decrypt?encryptedData=<Base64EncodedEncryptedData>

注意事项

  • 密钥管理:在实际应用中,密钥应该安全存储和管理,不要硬编码在代码中。
  • 异常处理:在生产代码中,应该有更完善的异常处理机制。
  • HTTPS:确保你的API通过HTTPS进行通信,以保护传输中的数据。

到此这篇关于Spring Boot 安全 API 构建:加密解密功能的卓越实践的文章就介绍到这了,更多相关Spring Boot API 加密解密内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • springboot 如何重定向redirect 并隐藏参数

    springboot 如何重定向redirect 并隐藏参数

    这篇文章主要介绍了springboot 如何重定向redirect 并隐藏参数的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-09-09
  • java 数值类型分秒时间格式化的实例代码

    java 数值类型分秒时间格式化的实例代码

    这篇文章主要介绍了java 数值类型分秒时间格式化的实例代码的相关资料,将秒或分钟的值转换为xx天xx小时xx分钟xx秒 如果 “xx” 为0 自动缺省,需要的朋友可以参考下
    2017-07-07
  • Spring BeanFactory和FactoryBean有哪些区别

    Spring BeanFactory和FactoryBean有哪些区别

    这篇文章主要介绍了Spring BeanFactory 与 FactoryBean 的区别详情,BeanFactory 和 FactoryBean 的区别却是一个很重要的知识点,在本文中将结合源码进行分析讲解,需要的小伙伴可以参考一下
    2023-02-02
  • Mybatis Mapper接口工作原理实例解析

    Mybatis Mapper接口工作原理实例解析

    这篇文章主要介绍了Mybatis Mapper接口工作原理实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-03-03
  • Spring Boot面试题总结

    Spring Boot面试题总结

    这篇文章主要介绍了Spring Boot面试题总结,本文给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下
    2019-09-09
  • Spring使用Configuration注解管理bean的方式详解

    Spring使用Configuration注解管理bean的方式详解

    在Spring的世界里,Configuration注解就像是一位细心的园丁,它的主要职责是在这个繁花似锦的园子里,帮助我们声明和管理各种各样的bean,本文给大家介绍了在Spring中如何优雅地管理你的bean,需要的朋友可以参考下
    2024-05-05
  • 细致解读希尔排序算法与相关的Java代码实现

    细致解读希尔排序算法与相关的Java代码实现

    这篇文章主要介绍了希尔排序算法与相关的Java代码实现,希尔排序的时间复杂度根据步长序列的不同而不同,需要的朋友可以参考下
    2016-05-05
  • Java中synchronized实现原理详解

    Java中synchronized实现原理详解

    这篇文章主要介绍了Java中synchronized实现原理详解,涉及synchronized实现同步的基础,Java对象头,Monitor,Mark Word,锁优化,自旋锁等相关内容,具有一定借鉴价值,需要的朋友可以参考下。
    2017-11-11
  • Java中间的接口用法详解

    Java中间的接口用法详解

    Java 程序员都知道要面向接口编程,那 Java​ 中的接口除了定义接口方法之外还能怎么用你知道吗,今天小编就来带大家看一下 Java 中间的接口还可以有哪些用法,需要的朋友可以参考下
    2023-07-07
  • 关于Filter中获取请求体body后再次读取的问题

    关于Filter中获取请求体body后再次读取的问题

    这篇文章主要介绍了关于Filter中获取请求体body后再次读取的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-03-03

最新评论