您可以使用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;
}