2016-04-24 171 views
17

当作为非特权用户运行Files.walk(Paths.get("/var/")).count()时,执行可能会引发异常,因为/var/内需要遍历root权限的文件夹。有没有办法让Java应用程序获得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权限吗?

+4

如果有可能,那么这将是一个主要的安全问题...想象一下,应用程序获得root权限并执行“rm -rf /”。哎呀。 – Tunaki

+7

该应用可以弹出一个对话框并要求用户输入sudo/root密码。许多本机应用程序已具备此功能。例如。 Gnome软件,磁盘工具等。 ;-) – Behrang

+0

我认为一般的方法是获取admin/root登录信息,然后产生一个与该用户分开的进程,并让该独立进程完成工作。您可能必须在每个平台上以不同方式执行此操作。我不知道是否有一个跨平台的框架可以为你处理这个问题(正如你可能知道的那样,要求其中一个将会是OT)。例如,请参阅[这里](http://stackoverflow.com/q/4662574/1076640)的Windows答案。 – yshavit

回答

3

短短几年经过充分测试的想法:

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'"

或者是使用的东西nicer-使用gksudo看。注意'"

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

跨平台

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

+2

但是,根据您的应用程序,请记住,以root权限运行您的应用程序可能会引入更多有害的漏洞。例如,当您使用Rhino引擎时,存在注入漏洞,它允许攻击者通过引擎注入任意Java代码。在这种情况下,这个注入的代码是以root权限运行的。 – Max

9

如果你想实际上是跳绳,你有没有访问的路径是什么,你有两种方法:

In the answer to this question阐述了如何获得一个子树中的所有文件的流你可以访问。

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

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 docs

FileVisitor tutorial

希望它能帮助。

+2

我的建议是从FileVisitor实现'visitFileFailed'方法,当文件无法访问时调用该方法。当您向此方法添加'返回FileVisitResult.SKIP_SUBTREE;'时,将不会引发AccessDeniedException。 –

+0

你是对的!我会尽快更新答案。 – Linuslabo

1

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

相关问题