在Java项目中,我们经常需要把包含敏感信息的XML文件传到远程服务,但又不希望明文暴露。使用AES对称加密对XML中的关键节点内容加密,是最实用的做法之一。下面先看一张示意图了解整体流程。
整体实现思路
核心步骤分为四步:读取XML文档、定位目标节点、用AES算法加密节点文本、将修改后的文档写成文件并上传。加密时推荐使用AES/CBC/PKCS5Padding模式,并随机生成IV向量。
依赖与准备
本文示例基于JDK自带的javax.xml和javax.crypto包,不需要额外引入第三方加密库。XML解析使用DOM方式,方便修改节点。
密钥与IV生成
AES密钥长度可选128、192或256位。以下代码展示如何生成128位密钥和随机IV:
import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import java.security.SecureRandom;
public class KeyUtil {
// 生成AES密钥
public static SecretKey genKey() throws Exception {
KeyGenerator kg = KeyGenerator.getInstance("AES");
kg.init(128, new SecureRandom());
return kg.generateKey();
}
// 生成随机IV
public static IvParameterSpec genIv() {
byte[] iv = new byte[16];
new SecureRandom().nextBytes(iv);
return new IvParameterSpec(iv);
}
}
加密XML节点内容
下面示例读取input.xml,把<password>节点的文本加密后写回,并保存为新文件:
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import javax.xml.parsers.*;
import javax.xml.transform.*;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import org.w3c.dom.*;
import java.io.*;
import java.util.Base64;
public class XmlEncrypt {
public static void encryptNode(String src, String dest, SecretKey key, IvParameterSpec iv) throws Exception {
DocumentBuilder db = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document doc = db.parse(new File(src));
// 找到password节点
Node node = doc.getElementsByTagName("password").item(0);
String plain = node.getTextContent();
// AES加密
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
byte[] enc = cipher.doFinal(plain.getBytes("UTF-8"));
// 写回Base64密文
node.setTextContent(Base64.getEncoder().encodeToString(enc));
// 保存文件
Transformer tf = TransformerFactory.newInstance().newTransformer();
tf.transform(new DOMSource(doc), new StreamResult(new File(dest)));
}
}
上传加密后的XML文件
加密完成后的文件可通过HttpURLConnection上传,示例如下:
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
public class Uploader {
public static void upload(String filePath, String uploadUrl) throws Exception {
URL u = new URL(uploadUrl);
HttpURLConnection conn = (HttpURLConnection) u.openConnection();
conn.setRequestMethod("POST");
conn.setDoOutput(true);
conn.setRequestProperty("Content-Type", "application/xml");
try (FileInputStream fis = new FileInputStream(filePath);
OutputStream os = conn.getOutputStream()) {
byte[] buf = new byte[4096];
int len;
while ((len = fis.read(buf)) != -1) {
os.write(buf, 0, len);
}
}
int code = conn.getResponseCode();
System.out.println("上传响应码: " + code);
}
}
注意事项
- IV不需要保密,但可以随文件一起传给服务端用于解密。
- 密钥应通过安全渠道分发,不要硬编码在代码里。
- 如果节点不存在,代码需做空值判断避免异常。
通过上述方式,我们就能用Java完成AES加密XML节点并上传文件的完整流程,在保障数据安全的同时保持接口可用。