繁体   English   中英

Java应用程序是否有获得root权限的方法?

[英]Is there a way for a Java app to gain root permissions?

当运行Files.walk(Paths.get("/var/")).count()作为非特权用户时,执行可能会抛出异常,因为/var/中的文件夹需要遍历root权限。

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

我只想确保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等应用程序在通过java -jar app.jar等方法从命令行执行后获得root权限?

如果你想要的实际上是跳过你无法访问的路径,你有两种方法:

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

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

FileVisitor的

使用FileVisitor会添加大量代码,但在处理目录树时可以提供更大的灵活性。 要解决同样的问题,您可以将Files.walk()替换为:

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

扩展SimpleFileVisitor(计算文件)并覆盖一些方法。

您可以:

  1. 覆盖visitFileFailed方法,处理由于某些原因无法访问文件的情况; (Lukasz_Plawny的建议)
  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;

}

FileVisitor文档

FileVisitor教程

希望能帮助到你。

只是一些完全没有经过考验的想法:

1)使用root权限运行您的应用程序以开始:

sudo java -jar myapp.jar

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

java -jar myapp.jar

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

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

或者使用gksudo使用更好看的东西。 记住'"

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

跨平台

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

没有简单的方法来更改权限。 Java并不擅长这些任务。 在启动时只有一些技巧,如检查权限,并尝试通过su / sudo更改权限,然后重新启动应用程序或使用Java-gnome。 请在这里阅读更多内容: Java:在Ubuntu上询问root权限

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM