mirror of
https://github.com/zfile-dev/zfile.git
synced 2025-04-19 05:34:52 +00:00
✨ 优化本地存储检测安全性的代码
This commit is contained in:
@@ -45,7 +45,7 @@ import java.util.List;
|
||||
@Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
|
||||
@Slf4j
|
||||
public class LocalServiceImpl extends AbstractProxyTransferService<LocalParam> {
|
||||
|
||||
|
||||
private static final String PREVIEW_PARAM_NAME = "preview";
|
||||
|
||||
@Override
|
||||
@@ -91,7 +91,7 @@ public class LocalServiceImpl extends AbstractProxyTransferService<LocalParam> {
|
||||
@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<LocalParam> {
|
||||
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<LocalParam> {
|
||||
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<LocalParam> {
|
||||
public boolean deleteFolder(String path, String name) {
|
||||
checkPathSecurity(path);
|
||||
checkNameSecurity(name);
|
||||
|
||||
|
||||
return deleteFile(path, name);
|
||||
}
|
||||
|
||||
@@ -137,9 +137,8 @@ public class LocalServiceImpl extends AbstractProxyTransferService<LocalParam> {
|
||||
@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<LocalParam> {
|
||||
|
||||
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<LocalParam> {
|
||||
@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<LocalParam> {
|
||||
@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<LocalParam> {
|
||||
@Override
|
||||
public ResponseEntity<Resource> 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<LocalParam> {
|
||||
|
||||
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<LocalParam> {
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user