我正在编写一个Java程序,它读取用户的一些输入,这些输入应该是预定义文件夹的相对路径。例如,他将输入test / subfolder,我将生成/path/to/test/subfolder
。
我如何检查并阻止用户输入类似../../../
的内容,这会弄乱路径并允许他访问不允许的路径?
答案 0 :(得分:1)
使用Java 7+,使用Path
个对象,您可以在创建最终路径之前调用normalize()
方法。该方法将通过取消..
和前一个路径段并删除任何.
段来规范化路径。
有几个案例需要考虑。如果提供的路径是相对的,例如
../first/second
在这种情况下,规范化无法删除..
,因为它不知道它之前会是什么。您所要做的就是在根/
上解析此路径。例如
Path path = Paths.get("../first");
path = Paths.get("/").resolve(path.normalize()).normalize();
路径可以包含任意数量的..
。
Path path = Paths.get("../../../../first/../second/../../more");
path = Paths.get("/").resolve(path.normalize()).normalize();
该过程将持续应用。
还有一种情况是提供的路径是绝对的。在这种情况下,您可以立即将其标准化。
Path path = Paths.get("/../../../../first/../second/../../more").normalize();
然后,您可以解析针对前缀路径提供的路径(如果提供的路径是绝对路径,请小心。)
对于其他人提出的符号链接,在使用java.nio.file.LinkOption.NOFOLLOW_LINKS
时继续使用java.nio.Files
的NIO。
答案 1 :(得分:1)
为了更加一致,我会让他写下他想要的东西,并在他选择路径后检查是否允许(获取所选文件并检查其路径)。他可能会找到一种你没想过的方法,例如别名。
此外(有点指出),如果您希望界面是用户友好的并且在选择路径时已经禁止通知它,请使用正则表达式检查输入路径中是否有../(或者只是进行pathString.indexOf( "../" ) == -1
检查)
答案 2 :(得分:1)
之前我正好尝试过这个问题。如果使用类似
之类的内容将预定义文件夹与路径合并new Path(basePath, givenRelativePath);
然后我不知道除..
之外的任何其他内容会导致 baseDir 之外的结果(当然,假设没有符号链接指向外部)。因此,最简单的检查是检测两个连续点的存在,就像丹尼尔建议的那样。
如果你想绝对确定(并且还要处理符号链接或其他有潜在危险的东西),你可以检查这样的结果(只是草图):
if (givenPath.indexOf("..") >= 0)
throw new IllegalArgumentException();
File result = new File(basePath, givenPath);
if (!result.getCanonicalPath().startsWith(basePath.getCanonicalPath()))
throw new IllegalArgumentException();
serveFile(result);
这基本上是几个月前我结束的。
当然,在Java 7+中,您可以使用Path
和normalize
方法而不是getCanonicalPath
,这样会更快,并且不会触及文件系统。另一方面,它不考虑符号链接和其他东西。
答案 3 :(得分:1)
如果你真的想忽略用户输入,如果以'的形式输入相对路径。'或者' ..', 你可以尝试一下.. enter link description here
File f = new File("/../../../../path/to/folder"); // Wrong user input
Path path = f.toPath();
String str1 = path.normalize().toString(); // ouout -> /path/to/folder