Java 应用程序有没有办法获得 root 权限?

2022-09-03 02:25:31

以非特权用户身份运行时,执行可能会引发异常,因为其中存在需要 root 权限才能遍历的文件夹。Files.walk(Paths.get("/var/")).count()/var/

我不是在寻找一种以root身份执行bash命令的方法(例如,使用等)。sudo find /varProcess

我只想确保不会抛出一个:Files.walk(Paths.get("/var/")).count()AccessDeniedException

Exception in thread "restartedMain" java.lang.reflect.InvocationTargetException
    at sun.reflect.NativeMethodAccessorImpl.invoke0
    at sun.reflect.NativeMethodAccessorImpl.invoke
    at sun.reflect.DelegatingMethodAccessorImpl.invoke
    at java.lang.reflect.Method.invoke
    at org.springframework.boot.devtools.restart.RestartLauncher.run
Caused by: java.io.UncheckedIOException: java.nio.file.AccessDeniedException: /var/cache/httpd
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded
    at java.nio.file.FileTreeIterator.hasNext
    at java.util.Iterator.forEachRemaining
    at java.util.Spliterators$IteratorSpliterator.forEachRemaining
    at java.util.stream.AbstractPipeline.copyInto
    at java.util.stream.AbstractPipeline.wrapAndCopyInto
    at java.util.stream.ReduceOps$ReduceOp.evaluateSequential
    at java.util.stream.AbstractPipeline.evaluate
    at java.util.stream.LongPipeline.reduce
    at java.util.stream.LongPipeline.sum
    at java.util.stream.ReferencePipeline.count
    at com.example.DemoApplication.main
    ... 5 more
Caused by: java.nio.file.AccessDeniedException: /var/cache/httpd
    at sun.nio.fs.UnixException.translateToIOException
    at sun.nio.fs.UnixException.rethrowAsIOException
    at sun.nio.fs.UnixException.rethrowAsIOException
    at sun.nio.fs.UnixFileSystemProvider.newDirectoryStream
    at java.nio.file.Files.newDirectoryStream
    at java.nio.file.FileTreeWalker.visit
    at java.nio.file.FileTreeWalker.next
    at java.nio.file.FileTreeIterator.fetchNextIfNeeded

这只是一个例子。使用它可以解决异常。但是这个例子也可以扩展到其他用例。filter(...)

因此,简而言之,对于CLI,JavaFX等应用程序来说,在通过诸如此类的方法从命令行执行后,这完全有可能获得root权限吗?java -jar app.jar


答案 1

如果您想要的是跳过您无权访问的路径,则有两种方法:

在对这个问题的回答中,解释了如何获取可以访问的子树的所有文件的流。

但是这个例子也可以扩展到其他用例。

文件访问器

使用 a 会添加大量代码,但在遍历目录树时会为您提供更大的灵活性。要解决相同的问题,您可以替换为:FileVisitorFiles.walk()

Files.walkFileTree(Path start, FileVisitor<? super Path> visitor);

扩展 SimpleFileVisitor(对文件进行计数)并重写某些方法。

您可以:

  1. 覆盖该方法,以处理由于某些原因无法访问文件的情况;(Lukasz_Plawny的建议)visitFileFailed
  2. (可选)覆盖该方法,在访问目录之前检查权限:如果您无法访问它,则可以简单地跳过其子树(请记住,您可能能够访问目录,但不能访问其所有文件);preVisitDirectory

例如 1

@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
    // you can log the exception 'exc'
    return FileVisitResult.SKIP_SUBTREE;
}

例如 2

@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {

    if(!Files.isReadable(dir))
        return FileVisitResult.SKIP_SUBTREE;

    return FileVisitResult.CONTINUE;

}

文件访问器文档

文件访问器教程

希望它有帮助。


答案 2

只是一些完全未经测试的想法:

1) 使用根权限运行应用,首先执行以下操作:

sudo java -jar myapp.jar

2) 让你的应用启动一个请求 root 权限的启动器类,然后继续运行应用的其余部分:

java -jar myapp.jar

这反过来又执行一个shell命令,但只是一个xterm,它提示输入root密码,然后继续运行具有root权限的java程序:

xterm -e "sudo sh -c 'java -jar /tmp/myrootapp.jar'"

或者使用gksudo使用更好看的东西。注意 和 .'"

也许提取本身到一个临时目录。 包含,因此它可以如上所述启动它。 当然,应该从java中检索,最好是一个具有随机名称的目录,只有运行的用户才能访问该目录,以防止注入。myapp.jarmyapp.jarmyrootapp.jar/tmpmyapp.jarmyrootapp.jar

跨平台

你提到了你自己,所以我假设你是在某种Linux上。如果这应该跨平台工作,例如在Macintosh或Microsoft Windows上,您需要首先进行某种系统识别。然后,您可以在代码中应用策略模式来处理获取root或管理员权限的各种方式。/var/myrootapp.jar


推荐