修复漏洞问题

This commit is contained in:
sh
2026-05-02 20:41:29 +08:00
parent 0b3a3b4da6
commit 35feb9a147
7 changed files with 235 additions and 10 deletions

View File

@@ -2,12 +2,14 @@ package com.ruoyi.cms.controller.app;
import com.ruoyi.cms.util.IdGenerator;
import com.ruoyi.cms.util.ProxyServerUtil;
import com.ruoyi.cms.util.file.FileValid;
import com.ruoyi.common.core.domain.entity.File;
import com.ruoyi.cms.service.IFileService;
import com.ruoyi.common.core.controller.BaseController;
import com.ruoyi.common.core.domain.AjaxResult;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.common.utils.ServletUtils;
import com.ruoyi.common.utils.SiteSecurityUtils;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
@@ -15,6 +17,8 @@ import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
@RestController
@@ -25,19 +29,54 @@ public class AppFileController extends BaseController {
@Autowired
private IdGenerator idGenerator;
//文件大小限制 10MB
private static final long MAX_FILE_SIZE = 10 * 1024 * 1024;
@ApiOperation("上传文件")
@PostMapping("/upload")
public AjaxResult upload(@RequestParam("file") MultipartFile file, @RequestParam(value = "bussinessid",required = false) Long bussinessId) {
if(!(SiteSecurityUtils.isLogin() || SecurityUtils.isLogin())){
if (file.isEmpty()) return AjaxResult.error("文件不能为空!");
if (file.getSize() > MAX_FILE_SIZE) {
return AjaxResult.error("文件大小超出限制!");
}
if(!(SiteSecurityUtils.isLogin() || SecurityUtils.isLogin())){
return AjaxResult.error("未登录,请登录后在上传文件!");
}
}
boolean isValid = FileValid.validateFile(file);
if (!isValid) {
return AjaxResult.error("文件类型不合法或内容被篡改!");
}
return fileService.upload(file,bussinessId);
}
@ApiOperation("获取附件列表")
@GetMapping("/list")
public TableDataInfo list(File file)
public TableDataInfo list(File file,HttpServletRequest request)
{
String host = request.getHeader("Host");
List<String> allowedHosts = Arrays.asList(
"localhost",
"127.0.0.1",
"10.98.80.146",
"10.98.80.50",
"www.xjksly.cn",
"ks.zhaopinzao8dian.com"
);
if (host != null) {
if (host.contains(":")) {
host = host.split(":")[0];
}
if (!allowedHosts.contains(host)) {
return error(401,"非法请求来源");
}
}
//修复CORS 跨域漏洞
HttpServletResponse response = ServletUtils.getResponse();
response.setHeader("Access-Control-Allow-Origin", "");
response.setHeader("Access-Control-Allow-Credentials", "");
if(file.getBussinessid()==null){
return error(400,"无效的业务id!");
}
@@ -55,11 +94,19 @@ public class AppFileController extends BaseController {
@ApiOperation("上传文件")
@PostMapping("/uploadFile")
public AjaxResult uploadFile(@RequestParam("file") MultipartFile file, @RequestParam(value = "bussinessid",required = false) Long bussinessId, HttpServletRequest request) {
String proxyServer = ProxyServerUtil.getProxyServer(request);
System.out.println("获取服务器地址======================"+proxyServer);
if (file.isEmpty()) return AjaxResult.error("文件不能为空!");
if (file.getSize() > MAX_FILE_SIZE) {
return AjaxResult.error("文件大小超出限制!");
}
if(!(SiteSecurityUtils.isLogin() || SecurityUtils.isLogin())){
return AjaxResult.error("未登录,请登录后在上传文件!");
}
boolean isValid = FileValid.validateFile(file);
if (!isValid) {
return AjaxResult.error("文件类型不合法或内容被篡改!");
}
String proxyServer = ProxyServerUtil.getProxyServer(request);
System.out.println("获取服务器地址======================"+proxyServer);
if(bussinessId==null){
bussinessId=idGenerator.generateId();
}

View File

@@ -117,10 +117,14 @@ public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements IF
throw new SecurityException("非法路径,禁止访问");
}
// 保存文件到服务器
Files.copy(file.getInputStream(), filePath);
java.io.File destFile = filePath.toFile();
destFile.setReadable(true, false); // 所有用户可读
destFile.setWritable(false); // 禁止写入
destFile.setExecutable(false);
// 保存文件信息到数据库
saveFileInfo(fileName, bussinessid);
@@ -163,6 +167,11 @@ public class FileServiceImpl extends ServiceImpl<FileMapper, File> implements IF
// 保存文件到服务器
Files.copy(file.getInputStream(), filePath);
java.io.File destFile = filePath.toFile();
destFile.setReadable(true, false); // 所有用户可读
destFile.setWritable(false); // 禁止写入
destFile.setExecutable(false);
// 保存文件信息到数据库
File svFile=saveFileInfo(fileName, bussinessid);
AjaxResult ajaxResult=AjaxResult.success();

View File

@@ -0,0 +1,84 @@
package com.ruoyi.cms.util.file;
import org.springframework.web.multipart.MultipartFile;
import java.util.Arrays;
import java.util.List;
/**
* 文件校验
*/
public class FileValid {
/**
* 白名单配置
*/
final static List<String> allowedExt = Arrays.asList(
"jpg", "jpeg", "png", "gif", "pdf",
"doc", "docx", "wps",
"xls", "xlsx",
"ppt", "pptx"
);
/**
* 支持的MIME类型
*/
final static List<String> allowedMime = Arrays.asList(
"image/jpeg", "image/png", "image/gif", "application/pdf",
"application/msword",
"application/vnd.openxmlformats-officedocument.wordprocessingml.document",
"application/vnd.ms-works", // wps
"application/vnd.ms-excel",
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"application/vnd.ms-powerpoint",
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
);
/**
* 魔数校验
*/
final static List<String> allowedMagic = Arrays.asList(
"ffd8ffe0", "ffd8ffe1", // jpg
"89504e47", // png
"47494638", // gif
"25504446" // pdf
);
/**
* 文件类型 + MIME + 魔数 三重验证
* @param file
* @return
*/
public static boolean validateFile(MultipartFile file) {
try {
// 白名单配置
String originalFilename = file.getOriginalFilename().toLowerCase();
String contentType = file.getContentType();
String ext = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);
// 扩展名 + MIME 校验
if (!allowedExt.contains(ext) || !allowedMime.contains(contentType)) {
return false;
}
return true;
} catch (Exception e) {
return false;
}
}
/**
* 字节转16进制魔数校验用
* @param bytes
* @return
*/
private static String bytesToHex(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02x", b));
}
return sb.toString();
}
}