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