WildFly与PrimeFaces文件上传定制:加密临时文件
实现WildFly 26(Undertow)与PrimeFaces上传临时文件加密
针对Undertow原生Multipart解析和PrimeFaces+Commons FileUpload两种场景,分别提供临时文件加密的实现方案:
一、Undertow原生Multipart上传加密
Undertow通过MultiPartUploadHandler创建上传临时文件,可通过自定义FileFactory替换默认的临时文件创建逻辑,实现加密写入。
1. 自定义加密版FileFactory
实现Undertow的FileFactory接口,在创建临时文件输出流时,用加密流包装:
import io.undertow.server.handlers.form.FileFactory; import javax.crypto.Cipher; import javax.crypto.CipherOutputStream; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStream; import java.nio.file.Files; import java.security.SecureRandom; public class EncryptedTempFileFactory implements FileFactory { // 建议从安全配置源读取密钥,而非硬编码 private final byte[] encryptionKey = System.getenv("UPLOAD_ENCRYPT_KEY").getBytes(); private final String cipherAlgorithm = "AES/CBC/PKCS5Padding"; @Override public OutputStream createFile(File file) throws IOException { Files.createFile(file.toPath()); FileOutputStream fos = new FileOutputStream(file); try { // 生成随机IV(AES-IV固定16字节) SecureRandom secureRandom = new SecureRandom(); byte[] iv = new byte[16]; secureRandom.nextBytes(iv); // 将IV写入文件开头,解密时需先读取 fos.write(iv); // 初始化加密Cipher SecretKeySpec keySpec = new SecretKeySpec(encryptionKey, "AES"); Cipher cipher = Cipher.getInstance(cipherAlgorithm); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); return new CipherOutputStream(fos, cipher); } catch (Exception e) { fos.close(); Files.deleteIfExists(file.toPath()); throw new IOException("Failed to initialize encrypted stream", e); } } @Override public File createTempFile(String prefix, String suffix, File directory) throws IOException { // 复用默认临时文件路径生成逻辑 return File.createTempFile(prefix, suffix, directory); } }
2. 配置Undertow使用自定义FileFactory
编程式配置(嵌入式/自定义部署)
在Undertow部署配置中替换默认的Multipart工厂:
import io.undertow.servlet.api.DeploymentInfo; import io.undertow.servlet.api.MultiPartConfigFactory; // 构建部署信息时配置 DeploymentInfo deploymentInfo = new DeploymentInfo() .setContextPath("/your-app") .setDeploymentName("your-app.war") // 其他Servlet/过滤器配置... .setMultipartConfigFactory(new MultiPartConfigFactory() .setFileFactory(new EncryptedTempFileFactory()));
WildFly容器配置
若使用WildFly standalone服务器,需将自定义类打包为WildFly模块,在jboss-deployment-structure.xml中声明依赖,再通过CDI扩展或自定义Undertow Servlet容器配置替换FileFactory。
二、PrimeFaces + Commons FileUpload加密
PrimeFaces使用Commons FileUpload时,临时文件由DiskFileItemFactory创建,可通过继承该类并重写文件项创建逻辑实现加密。
1. 自定义加密版DiskFileItemFactory
import org.apache.commons.fileupload.disk.DiskFileItem; import org.apache.commons.fileupload.disk.DiskFileItemFactory; import org.apache.commons.fileupload.FileItem; import javax.crypto.Cipher; import javax.crypto.CipherOutputStream; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; import java.io.FileOutputStream; import java.io.IOException; import java.security.SecureRandom; public class EncryptedDiskFileItemFactory extends DiskFileItemFactory { private final byte[] encryptionKey = System.getenv("UPLOAD_ENCRYPT_KEY").getBytes(); private final String cipherAlgorithm = "AES/CBC/PKCS5Padding"; @Override public FileItem createItem(String fieldName, String contentType, boolean isFormField, String fileName) { DiskFileItem item = (DiskFileItem) super.createItem(fieldName, contentType, isFormField, fileName); try { FileOutputStream fos = new FileOutputStream(item.getStoreLocation()); // 生成随机IV并写入文件开头 SecureRandom secureRandom = new SecureRandom(); byte[] iv = new byte[16]; secureRandom.nextBytes(iv); fos.write(iv); // 初始化加密Cipher SecretKeySpec keySpec = new SecretKeySpec(encryptionKey, "AES"); Cipher cipher = Cipher.getInstance(cipherAlgorithm); cipher.init(Cipher.ENCRYPT_MODE, keySpec, new IvParameterSpec(iv)); // 替换文件项的输出流为加密流 item.setOutputStream(new CipherOutputStream(fos, cipher)); } catch (Exception e) { item.delete(); throw new RuntimeException("Failed to create encrypted temp file", e); } return item; } }
2. 配置PrimeFaces使用自定义工厂
在faces-config.xml中配置FileUpload过滤器,指定自定义工厂类:
<filter> <filter-name>PrimeFaces FileUpload Filter</filter-name> <filter-class>org.primefaces.webapp.filter.FileUploadFilter</filter-class> <init-param> <param-name>uploader</param-name> <param-value>commons</param-value> </init-param> <init-param> <param-name>factory</param-name> <param-value>com.your.package.EncryptedDiskFileItemFactory</param-value> </init-param> </filter>
关键注意事项
- 密钥管理:绝对禁止硬编码密钥,应使用WildFly安全Vault、环境变量或密钥管理服务(KMS)存储和读取密钥。
- 解密逻辑:读取加密临时文件时,需先读取文件开头的IV,再初始化
Cipher.DECRYPT_MODE,用CipherInputStream读取内容。 - 性能考量:加密会增加CPU开销,需根据业务并发量测试性能,必要时调整加密算法或优化IO逻辑。
- 临时文件清理:确保加密临时文件在使用后正常删除,避免磁盘空间泄漏。
内容的提问来源于stack exchange,提问作者László Tóth
相关产品推荐
相关产品推荐

