如何在Spring Boot中实现前后端数据的加密通信

在现代Web应用中,如何确保前后端通信的安全性是非常重要的操作。而加密通信则是一种很有效的保护数据安全性的方法。下面我们就来介绍一下如何在Spring Boot中实现前后端数据加密通信。

为什么需要加密通信?

尽管HTTPS已经对数据传输进行了加密,但在某些情况下,我们仍需要对敏感数据进行额外加密,例如防止中间人攻击解密敏感数据,在某些特定环境中需要对数据进行加密传输,通过与HTTPS的双重加密操作来增加系统的安全性。

基本思路

加密通信的核心流程,在前端发送请求前对敏感数据进行加密操作。后端接收到加密数据后解密并处理。而后端在返回数据的时候对数据进行加密操作,而当前端收到数据之后对数据进行解密操作。而在实际开发中,我们可以选择的加密方式有很多,例如对称加密(AES)、非对称加密(RSA)、或者结合两者的混合加密方式。

下面我们就来看看详细的实现步骤。

使用RSA实现加密通信

RSA是一种非对称加密算法,常用于加密小数据或加密对称密钥。RSA 的核心是公钥和私钥。公钥用于加密,私钥用于解密。可以按照如下的步骤来进行操作。

准备公钥和私钥

生成密钥对可以通过工具(如 OpenSSL 或 Java 的 KeyPairGenerator)完成,如下所示。

# 生成私钥
openssl genpkey -algorithm RSA -out private_key.pem
# 从私钥生成公钥
openssl rsa -pubout -in private_key.pem -out public_key.pem

将生成的密钥放在资源目录src/main/resources/keys/中。

后端代码实现

添加RSA加解密工具类

import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.spec.*;
import javax.crypto.Cipher;
import java.util.Base64;

public class RSAUtil {

    private static final String RSA = "RSA";

    // 加载公钥
    public static PublicKey loadPublicKey(String publicKeyStr) throws Exception {
        byte[] decoded = Base64.getDecoder().decode(publicKeyStr);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(decoded);
        return keyFactory.generatePublic(keySpec);
    }

    // 加载私钥
    public static PrivateKey loadPrivateKey(String privateKeyStr) throws Exception {
        byte[] decoded = Base64.getDecoder().decode(privateKeyStr);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(decoded);
        return keyFactory.generatePrivate(keySpec);
    }

    // 加密
    public static String encrypt(String data, PublicKey publicKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }

    // 解密
    public static String decrypt(String data, PrivateKey privateKey) throws Exception {
        Cipher cipher = Cipher.getInstance(RSA);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(data));
        return new String(decrypted, StandardCharsets.UTF_8);
    }
}

Spring Boot接口示例

下面我们就可以在Controller层中实现,加载密钥并实现加解密API操作,如下所示。

@RestController
@RequestMapping("/api/secure")
public class SecureController {

    private final PrivateKey privateKey;
    private final PublicKey publicKey;

    public SecureController() throws Exception {
        // 加载密钥
        String privateKeyStr = new String(Files.readAllBytes(Paths.get("src/main/resources/keys/private_key.pem")));
        String publicKeyStr = new String(Files.readAllBytes(Paths.get("src/main/resources/keys/public_key.pem")));

        this.privateKey = RSAUtil.loadPrivateKey(privateKeyStr);
        this.publicKey = RSAUtil.loadPublicKey(publicKeyStr);
    }

    @PostMapping("/decrypt")
    public String decryptData(@RequestBody String encryptedData) throws Exception {
        return RSAUtil.decrypt(encryptedData, privateKey);
    }

    @GetMapping("/encrypt")
    public String encryptData(@RequestParam String data) throws Exception {
        return RSAUtil.encrypt(data, publicKey);
    }
}

前端实现加密解密

以JavaScript为例,使用crypto.subtle 或第三方库如node-rsa来实现前端的数据加解密操作,如下所示。

// 使用 Node.js 示例
const NodeRSA = require('node-rsa');
const fs = require('fs');

// 加载公钥
const publicKey = fs.readFileSync('public_key.pem', 'utf8');

// 加密
const key = new NodeRSA(publicKey);
key.setOptions({ encryptionScheme: 'pkcs1' });

const data = "Sensitive data";
const encrypted = key.encrypt(data, 'base64');
console.log("Encrypted:", encrypted);

// 解密(测试时需要私钥)
const privateKey = fs.readFileSync('private_key.pem', 'utf8');
const privateKeyInstance = new NodeRSA(privateKey);
const decrypted = privateKeyInstance.decrypt(encrypted, 'utf8');
console.log("Decrypted:", decrypted);

总结

通过上述步骤,我们就可以在Spring Boot应用中实现安全的前后端加密通信。根据具体需求,选择合适的加密方式,保障数据传输安全。

原文链接:,转发请注明来源!