1. 环境说明,此教程代码运行环境如下:
JDK
:JDK1.8+,
JclamAV Server
:1.1.0-rc,
Server
:CentOS8
2. 代码编辑
- jClamAV客户端依赖导入
<!--JClamAV客户端依赖-->
<dependency>
<groupId>xyz.capybara</groupId>
<artifactId>clamav-client</artifactId>
<version>2.1.2</version>
</dependency>
<!--hutool工具包依赖-->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>
<version>5.8.4</version>
</dependency>
- 编写配置类
JClamAVConfig
用于初始化ClamAV的客户端, 以及配置文件application.properties
,
application.properties如下:
#web服务端口
server.port=8080
#JclamAV服务端配置
env.clamav.uri=192.168.217.142:3310
JclamAVConfig类如下:
package com.darlingrin.jclamavdemo.config;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.env.Environment;
import xyz.capybara.clamav.ClamavClient;
import xyz.capybara.clamav.Platform;
/**
* @ClassName FileValidate
* @Description TODO
* @Author Rin
* @Date 2023/12/29 14:38
* @Version 1.0
**/
@Configuration
public class JClamAVConfig {
//日志记录
private static final Logger log = LoggerFactory.getLogger(JClamAVConfig.class);
//定义clamav相关配置的key(此项用于对application.properties或者application.yml配置文件中的key进行配置)
private final static String CLAMAV_URI = "env.clamav.uri";
//实例化Clamav客户端
public static ClamavClient client;
//注入Spring的环境配置管理对象
@Autowired
Environment environment;
/**
* 初始化客户端
* @return clamav客户端对象
*/
@Bean(name = "clamavClient")
public ClamavClient getClamavClient(){
try{
//获取application.properties中的jclamAV服务端配置
String uri = environment.getProperty(CLAMAV_URI);
//拆分端口ip(当然如果定义配置的时候ip和端口分开配置的直接分开获取即可)
String serverHost = uri.split(":")[0];
Integer serverPort = Integer.valueOf(uri.split(":")[1]);
//初始化ClamavClenet对象
client = new ClamavClient(serverHost,serverPort, Platform.UNIX);
log.info("Clamav Server Connected Successfully ..... in {}:{}",serverHost,serverPort);
//输出jclamav的版本
log.info(client.version());
return client;
}catch (Exception e){
log.error("Clamav Server Connect Failed,Caused By >>>>>>> ",e);
}
return null;
}
}
- 编写文件扫描工具类
FileScannerHelper
用于将对文件进行预处理以及参数处理
FileScannerHelper.java代码如下:
package com.darlingrin.jclamavdemo.tools;
import cn.hutool.core.io.IoUtil;
import com.darlingrin.jclamavdemo.config.JClamAVConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import xyz.capybara.clamav.ClamavClient;
import xyz.capybara.clamav.ClamavException;
import xyz.capybara.clamav.commands.scan.result.ScanResult;
import java.io.File;
import java.io.InputStream;
import java.util.Collection;
import java.util.Map;
/**
* @ClassName FileScanner
* @Description TODO
* @Author Rin
* @Date 2023/12/29 14:51
* @Version 1.0
**/
public class FileScannerHelper {
//日志记录
private static final Logger log = LoggerFactory.getLogger(FileScannerHelper.class);
private static ClamavClient client = JClamAVConfig.client;
/**
* 文件扫描走文件流的方式
* @param fileStream 传入文件流
* @return 0安全文件,1危险文件
* @throws ClamavException
*/
public static Integer FileScanner(InputStream fileStream) throws ClamavException {
try{
ScanResult scres = client.scan(fileStream);
if(scres instanceof ScanResult.OK){
//验证通过
return 0;
} else if (scres instanceof ScanResult.VirusFound) {
Map<String, Collection<String>> foundViruses = ((ScanResult.VirusFound) scres).getFoundViruses();
log.warn("Virus Found >>>> {}",foundViruses);
return -1;
}
}catch (ClamavException e){
log.error("ClamAV Scanned Error Caused By >>>>> {}",e);
throw e;
}
return 0;
}
/**
* 危险文件扫描走文件地址的方式*这个文件地址是指文件扫描服务器所在的文件地址
* @param file 文件对象
* @return 0安全,1危险
* @throws ClamavException
*/
public static Integer FileScanner(File file) throws ClamavException {
try{
ScanResult scres = client.scan(file.toPath());
if(scres instanceof ScanResult.OK){
//验证通过
return 0;
} else if (scres instanceof ScanResult.VirusFound) {
Map<String, Collection<String>> foundViruses = ((ScanResult.VirusFound) scres).getFoundViruses();
log.warn("Virus Found >>>> {}",foundViruses);
return -1;
}
}catch (ClamavException e){
log.error("ClamAV Scanned Error Caused By >>>>> {}",e);
//IoUtil走的hutool工具包里面的Io工具类
return FileScanner(IoUtil.toStream(file));
}
return 0;
}
}
- 接下来编写测试类,先放一个安全的文件进行处理,示例代码走的是文件流的方式进行操作,示例代码在test包下面进行测试,当然也可以导入spring-web的依赖写一个controller进行测试
注意:因为在进行环境配置的时候有用到spring的环境管理,因此测试代码也必须依赖spring环境,故不能以执行main方法的方式测试
测试类代码如下:
//读取文件
File file = new File("D:\\软件安装包分区\\dm8_20231113_x86_win_64.zip");
System.out.println("=============================File Scanner Start==============================");
System.out.println("File Name: "+file.getName());
//计算文件大小(单位为KB)
System.out.println("File Size: "+(file.length()/8/1024)+"KB");
Date st = new Date();
System.out.println("File Scaner StartTime: "+sdf.format(st));
//将文件转为文件流
InputStream ips = IoUtil.toStream(file);
//调用服务,进行文件扫描(核心调用就这一行代码)
Integer status = FileScannerHelper.FileScanner(ips);
//获取文件扫描结果
System.out.println("File Scaner Consequence: "+(status==0? "It's Safety":"Tt's Dangerous"));
//结束扫描
Date ed = new Date();
System.out.println("File Scaner EndTime: "+sdf.format(ed));
System.out.println("Scanner Time : "+(ed.getTime() - st.getTime())+"ms");
System.out.println("==============================File Scanner End===============================");
测试结果如下:
文件安全扫描结果截图
在进行病毒文件或者风险文件操作的时候,请在独立的容器中进行测试,禁止在本机进行测试,建议在虚拟机中进行测试,防止误操作导致系统崩溃
危险文件扫描结果截图