本文目录导读:

在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);
}
}
最佳实践建议
生产环境注意事项
- 密钥管理
// 使用配置中心管理密钥 @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使用以获得最佳安全保障。