小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
前言
本节介绍RuoYi-Vue的ruoyi-admin模块中的上传下载模块CommonController 部分的代码,通用上传下载是最容易写的,也是最难写的,因为有可能直接就造成别有用心之人借助你的功能将不应该下载的服务器文件下载下来了。
阻止任意文件下载漏洞
一开始下载这里的代码只是用了isValidFilename这个方法,
public static String FILENAME_PATTERN = "[a-zA-Z0-9_\\-\\|\\.\\u4e00-\\u9fa5]+";
/**
* 文件名称验证
*
* @param filename 文件名称
* @return true 正常 false 非法
*/
public static boolean isValidFilename(String filename)
{
return filename.matches(FILENAME_PATTERN);
}
可以看到这里只是验证了文件名称是不是英文数字中文,其实我觉得啥用都没有。但是这里放开了.造成的结果就是可以通过..跳到上层
修改之后的
/**
* 检查文件是否可下载
*
* @param resource 需要下载的文件
* @return true 正常 false 非法
*/
public static boolean checkAllowDownload(String resource)
{
// 禁止目录上跳级别
if (StringUtils.contains(resource, ".."))
{
return false;
}
// 检查允许下载的文件规则
if (ArrayUtils.contains(MimeTypeUtils.DEFAULT_ALLOWED_EXTENSION, FileTypeUtils.getFileType(resource)))
{
return true;
}
// 不在允许下载的文件规则
return false;
}
只有允许下载的文件后缀名的文件才可以下载。
实际上随着现在越来越多的网站开始使用OSS,做这种服务器上的通用上传下载的风险明显要大于收益了。 而且这个方法可以传入删除参数,如果一个用户有查看文件权限,那么他可以直接利用这个接口将服务器上的文件删掉,毕竟这里没有做权限控制。