diff --git a/src/main/java/im/zhaojun/zfile/module/storage/service/impl/LocalServiceImpl.java b/src/main/java/im/zhaojun/zfile/module/storage/service/impl/LocalServiceImpl.java index b778ac3..1bce68f 100644 --- a/src/main/java/im/zhaojun/zfile/module/storage/service/impl/LocalServiceImpl.java +++ b/src/main/java/im/zhaojun/zfile/module/storage/service/impl/LocalServiceImpl.java @@ -45,7 +45,7 @@ import java.util.List; @Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE) @Slf4j public class LocalServiceImpl extends AbstractProxyTransferService { - + private static final String PREVIEW_PARAM_NAME = "preview"; @Override @@ -91,7 +91,7 @@ public class LocalServiceImpl extends AbstractProxyTransferService { @Override public FileItemResult getFileItem(String pathAndName) { checkPathSecurity(pathAndName); - + String fullPath = StringUtils.concat(param.getFilePath(), pathAndName); File file = new File(fullPath); @@ -109,7 +109,7 @@ public class LocalServiceImpl extends AbstractProxyTransferService { public boolean newFolder(String path, String name) { checkPathSecurity(path); checkNameSecurity(name); - + String fullPath = StringUtils.concat(param.getFilePath(), path, name); return FileUtil.mkdir(fullPath) != null; } @@ -119,7 +119,7 @@ public class LocalServiceImpl extends AbstractProxyTransferService { public boolean deleteFile(String path, String name) { checkPathSecurity(path); checkNameSecurity(name); - + String fullPath = StringUtils.concat(param.getFilePath(), path, name); return FileUtil.del(fullPath); } @@ -129,7 +129,7 @@ public class LocalServiceImpl extends AbstractProxyTransferService { public boolean deleteFolder(String path, String name) { checkPathSecurity(path); checkNameSecurity(name); - + return deleteFile(path, name); } @@ -137,9 +137,8 @@ public class LocalServiceImpl extends AbstractProxyTransferService { @Override public boolean renameFile(String path, String name, String newName) { checkPathSecurity(path); - checkNameSecurity(name); - checkNameSecurity(newName); - + checkNameSecurity(name, newName); + // 如果文件名没变,不做任何操作. if (StrUtil.equals(name, newName)) { return true; @@ -147,12 +146,12 @@ public class LocalServiceImpl extends AbstractProxyTransferService { String srcPath = StringUtils.concat(param.getFilePath(), path, name); File file = new File(srcPath); - + boolean srcExists = file.exists(); if (!srcExists) { throw ExceptionUtil.wrapRuntime(new FileNotFoundException("文件夹不存在.")); } - + FileUtil.rename(file, newName, true); return true; } @@ -161,9 +160,8 @@ public class LocalServiceImpl extends AbstractProxyTransferService { @Override public boolean renameFolder(String path, String name, String newName) { checkPathSecurity(path); - checkNameSecurity(name); - checkNameSecurity(newName); - + checkNameSecurity(name, newName); + return renameFile(path, name, newName); } @@ -177,7 +175,7 @@ public class LocalServiceImpl extends AbstractProxyTransferService { @Override public void uploadFile(String pathAndName, InputStream inputStream) { checkPathSecurity(pathAndName); - + String baseFilePath = param.getFilePath(); String uploadPath = StringUtils.removeDuplicateSlashes(baseFilePath + ZFileConstant.PATH_SEPARATOR + pathAndName); // 如果目录不存在则创建 @@ -195,7 +193,7 @@ public class LocalServiceImpl extends AbstractProxyTransferService { @Override public ResponseEntity downloadToStream(String pathAndName) { checkPathSecurity(pathAndName); - + File file = new File(StringUtils.removeDuplicateSlashes(param.getFilePath() + ZFileConstant.PATH_SEPARATOR + pathAndName)); if (!file.exists()) { ByteArrayResource byteArrayResource = new ByteArrayResource("文件不存在或异常,请联系管理员.".getBytes(StandardCharsets.UTF_8)); @@ -206,19 +204,19 @@ public class LocalServiceImpl extends AbstractProxyTransferService { HttpServletRequest request = RequestHolder.getRequest(); String type = request.getParameter("type"); - + MediaType mimeType = MediaType.APPLICATION_OCTET_STREAM; if (StrUtil.equals(type, PREVIEW_PARAM_NAME)) { mimeType = MediaTypeFactory.getMediaType(file.getName()).orElse(MediaType.APPLICATION_OCTET_STREAM); } - + HttpHeaders headers = new HttpHeaders(); - + if (ObjectUtil.equals(mimeType, MediaType.APPLICATION_OCTET_STREAM)) { String fileName = file.getName(); headers.setContentDispositionFormData("attachment", StringUtils.encodeAllIgnoreSlashes(fileName)); } - + return ResponseEntity .ok() .headers(headers) @@ -243,39 +241,43 @@ public class LocalServiceImpl extends AbstractProxyTransferService { } return fileItemResult; } - - + + /** * 检查路径合法性: * - 只有以 . 开头的允许通过,其他的如 ./ ../ 的都是非法获取上层文件夹内容的路径. * - * @param path + * @param paths * 文件路径 * * @throws IllegalArgumentException 文件路径包含非法字符时会抛出此异常 */ - private static void checkPathSecurity(String path) { - // 路径中不能包含 .. 不然可能会获取到上层文件夹的内容 - if (StrUtil.containsAny(path, "../", "..\\")) { - throw new IllegalArgumentException("文件路径存在安全隐患: " + path); + private static void checkPathSecurity(String... paths) { + for (String path : paths) { + // 路径中不能包含 .. 不然可能会获取到上层文件夹的内容 + if (StrUtil.containsAny(path, "../", "..\\")) { + throw new IllegalArgumentException("文件路径存在安全隐患: " + path); + } } } - - + + /** * 检查路径合法性: * - 不为空,且不包含 \ / 字符 * - * @param name + * @param names * 文件路径 * * @throws IllegalArgumentException 文件名包含非法字符时会抛出此异常 */ - private static void checkNameSecurity(String name) { - // 路径中不能包含 .. 不然可能会获取到上层文件夹的内容 - if (StrUtil.containsAny(name, "\\", "/")) { - throw new IllegalArgumentException("文件名存在安全隐患: " + name); + private static void checkNameSecurity(String... names) { + for (String name : names) { + // 路径中不能包含 .. 不然可能会获取到上层文件夹的内容 + if (StrUtil.containsAny(name, "\\", "/")) { + throw new IllegalArgumentException("文件名存在安全隐患: " + name); + } } } - + } \ No newline at end of file