您可以使用 Path.normalize()
从路径中去除 “..” 元素(及其前面的元素)— 例如,它将变为 “a/b/../c“ 到 ”a/c”。请注意,它不会在路径的开头去除“..”,因为前面没有要删除的目录组件。因此,如果您要预置另一条路径,请先执行此操作,然后规范化结果。
还可以使用 Path.startsWith(Path)
来检查一个路径是否是另一个路径的后代。Path.isAbsolute()
毫不奇怪地告诉你,路径是绝对的还是相对的。
以下是我如何处理进入 API 的不受信任的路径:
/**
* Resolves an untrusted user-specified path against the API's base directory.
* Paths that try to escape the base directory are rejected.
*
* @param baseDirPath the absolute path of the base directory that all
user-specified paths should be within
* @param userPath the untrusted path provided by the API user, expected to be
relative to {@code baseDirPath}
*/
public Path resolvePath(final Path baseDirPath, final Path userPath) {
if (!baseDirPath.isAbsolute()) {
throw new IllegalArgumentException("Base path must be absolute");
}
if (userPath.isAbsolute()) {
throw new IllegalArgumentException("User path must be relative");
}
// Join the two paths together, then normalize so that any ".." elements
// in the userPath can remove parts of baseDirPath.
// (e.g. "/foo/bar/baz" + "../attack" -> "/foo/bar/attack")
final Path resolvedPath = baseDirPath.resolve(userPath).normalize();
// Make sure the resulting path is still within the required directory.
// (In the example above, "/foo/bar/attack" is not.)
if (!resolvedPath.startsWith(baseDirPath)) {
throw new IllegalArgumentException("User path escapes the base path");
}
return resolvedPath;
}