Java案例如何实现接口参数加密?

wen java案例 17

本文目录导读:

Java案例如何实现接口参数加密?

  1. 基础概念
  2. 使用AES对称加密实现
  3. 使用RSA非对称加密
  4. 使用自定义注解实现
  5. 完整的请求签名方案
  6. 最佳实践建议
  7. 完整的接口加密示例

在Java中实现接口参数加密,通常是为了保证数据在传输过程中的安全性,下面是几种常见的实现方式,从简单到复杂逐步介绍。

基础概念

接口参数加密通常涉及:

  • 对称加密(如AES):加密解密使用同一密钥,速度快
  • 非对称加密(如RSA):公钥加密、私钥解密,安全性高但速度慢
  • 混合加密:结合两者优点

使用AES对称加密实现

工具类实现

import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class AESUtils {
    private static final String ALGORITHM = "AES";
    private static final String TRANSFORMATION = "AES/ECB/PKCS5Padding";
    // 16位密钥(实际使用时应从配置读取)
    private static final String SECRET_KEY = "YourSecretKey16!";
    /**
     * AES加密
     */
    public static String encrypt(String data) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(
            SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.ENCRYPT_MODE, keySpec);
        byte[] encrypted = cipher.doFinal(data.getBytes(StandardCharsets.UTF_8));
        return Base64.getEncoder().encodeToString(encrypted);
    }
    /**
     * AES解密
     */
    public static String decrypt(String encryptedData) throws Exception {
        SecretKeySpec keySpec = new SecretKeySpec(
            SECRET_KEY.getBytes(StandardCharsets.UTF_8), ALGORITHM);
        Cipher cipher = Cipher.getInstance(TRANSFORMATION);
        cipher.init(Cipher.DECRYPT_MODE, keySpec);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        return new String(decrypted, StandardCharsets.UTF_8);
    }
}

Spring Boot拦截器实现

import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Map;
@Component
public class EncryptionInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest request, 
                            HttpServletResponse response, 
                            Object handler) throws Exception {
        // 获取加密参数
        String encryptedParams = request.getParameter("encryptedData");
        if (encryptedParams == null) {
            throw new RuntimeException("加密参数不能为空");
        }
        try {
            // 解密参数
            String decryptedParams = AESUtils.decrypt(encryptedParams);
            // 将解密后的参数设置到request中
            request.setAttribute("decryptedParams", decryptedParams);
            return true;
        } catch (Exception e) {
            throw new RuntimeException("参数解密失败", e);
        }
    }
}

在Controller中使用

@RestController
public class UserController {
    @PostMapping("/api/user/login")
    public Result login(@RequestAttribute("decryptedParams") String decryptedParams) {
        // 解析JSON格式的解密参数
        JSONObject params = JSON.parseObject(decryptedParams);
        String username = params.getString("username");
        String password = params.getString("password");
        // 业务处理
        return Result.success("登录成功");
    }
}

使用RSA非对称加密

工具类实现

import javax.crypto.Cipher;
import java.security.*;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class RSAUtils {
    private static final String ALGORITHM = "RSA";
    /**
     * 生成密钥对
     */
    public static KeyPair generateKeyPair() throws Exception {
        KeyPairGenerator generator = KeyPairGenerator.getInstance(ALGORITHM);
        generator.initialize(2048);
        return generator.generateKeyPair();
    }
    /**
     * 公钥加密
     */
    public static String encryptByPublicKey(String data, String publicKey) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(publicKey);
        X509EncodedKeySpec keySpec = new X509EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PublicKey pubKey = keyFactory.generatePublic(keySpec);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, pubKey);
        byte[] encrypted = cipher.doFinal(data.getBytes());
        return Base64.getEncoder().encodeToString(encrypted);
    }
    /**
     * 私钥解密
     */
    public static String decryptByPrivateKey(String encryptedData, String privateKey) throws Exception {
        byte[] keyBytes = Base64.getDecoder().decode(privateKey);
        PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(keyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(ALGORITHM);
        PrivateKey priKey = keyFactory.generatePrivate(keySpec);
        Cipher cipher = Cipher.getInstance(ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, priKey);
        byte[] decrypted = cipher.doFinal(Base64.getDecoder().decode(encryptedData));
        return new String(decrypted);
    }
}

使用自定义注解实现

定义加密注解

import java.lang.annotation.*;
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Encrypt {
}

AOP切面实现

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;
@Aspect
@Component
public class EncryptionAspect {
    @Around("@annotation(Encrypt)")
    public Object encryptResponse(ProceedingJoinPoint joinPoint) throws Throwable {
        // 执行原方法
        Object result = joinPoint.proceed();
        // 加密返回结果
        if (result != null) {
            String jsonResult = new ObjectMapper().writeValueAsString(result);
            String encryptedResult = AESUtils.encrypt(jsonResult);
            return Result.success(encryptedResult);
        }
        return result;
    }
}

完整的请求签名方案

更安全的方案包括参数加密 + 签名验证:

public class SecureApiClient {
    /**
     * 生成请求签名
     */
    public static String generateSignature(Map<String, String> params, String secretKey) {
        // 1. 参数排序
        TreeMap<String, String> sortedParams = new TreeMap<>(params);
        // 2. 拼接成字符串
        StringBuilder sb = new StringBuilder();
        for (Map.Entry<String, String> entry : sortedParams.entrySet()) {
            if (entry.getValue() != null && !entry.getValue().isEmpty()) {
                sb.append(entry.getKey()).append("=").append(entry.getValue()).append("&");
            }
        }
        sb.append("key=").append(secretKey);
        // 3. MD5加密
        return DigestUtils.md5DigestAsHex(sb.toString().getBytes()).toUpperCase();
    }
    /**
     * 验证签名
     */
    public static boolean verifySignature(Map<String, String> params, String secretKey, String signature) {
        String expectedSignature = generateSignature(params, secretKey);
        return expectedSignature.equals(signature);
    }
}

最佳实践建议

生产环境注意事项

  1. 密钥管理
    // 使用配置中心管理密钥
    @Value("${api.encryption.key}")
    private String encryptionKey;

// 定期更换密钥 @Scheduled(cron = "0 0 0 1 * ?") // 每月1号更新 public void updateKey() { // 更新密钥逻辑 }


2. **加密方式选择建议**
- 小数据量(<1KB):使用RSA直接加密
- 大数据量:使用AES加密 + RSA加密AES密钥
3. **安全增强**
```java
public class EnhancedEncryption {
    // 添加时间戳防重放攻击
    public static String encryptWithTimestamp(String data, String key) {
        String dataWithTimestamp = data + "|" + System.currentTimeMillis();
        return AESUtils.encrypt(dataWithTimestamp, key);
    }
    // 添加随机数
    public static String encryptWithNonce(String data, String key) {
        String nonce = UUID.randomUUID().toString().substring(0, 8);
        String dataWithNonce = nonce + data;
        return AESUtils.encrypt(dataWithNonce, key);
    }
}

完整的接口加密示例

@RestController
public class SecureController {
    @PostMapping("/api/secure/data")
    public Result securedEndpoint(@RequestBody EncryptedRequest request) {
        try {
            // 1. 验证签名
            boolean valid = SignatureValidator.verify(
                request.getEncryptedData(), 
                request.getSignature(),
                secretKey
            );
            if (!valid) {
                return Result.error("签名验证失败");
            }
            // 2. 解密数据
            String decryptedData = AESUtils.decrypt(request.getEncryptedData());
            JSONObject data = JSON.parseObject(decryptedData);
            // 3. 检查时间戳(防止重放攻击)
            long timestamp = data.getLong("timestamp");
            if (System.currentTimeMillis() - timestamp > 300000) { // 5分钟有效期
                return Result.error("请求已过期");
            }
            // 4. 业务处理
            return processBusiness(data);
        } catch (Exception e) {
            return Result.error("解密失败: " + e.getMessage());
        }
    }
}

是实现Java接口参数加密的几种常见方式,实际项目中,建议根据安全性要求、性能需求和业务场景选择合适的方案,并配合HTTPS使用以获得最佳安全保障。

抱歉,评论功能暂时关闭!