Подтвердить что ты не робот

Есть ли способ для приложения Java получить права root?

При запуске Files.walk(Paths.get("/var/")).count() в качестве непривилегированного пользователя выполнение может вызвать исключение, так как есть папки внутри /var/, для которых требуется разрешение root.

Я не ищет способ выполнить команду bash как root (например, 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 и т.д., чтобы получить права root после того, как они были выполнены из командной строки с помощью метода, такого как java -jar app.jar?

4b9b3361

Ответ 1

Если то, что вы хотите, фактически пропускает пути, в которых у вас нет доступа, вы имеете два подхода:

Струйные

В ответе на этот вопрос объясняется, как получить поток всех файлов поддерева, к которым вы можете получить доступ.

Но этот пример может быть расширен и в других случаях использования.

FileVisitor

Использование FileVisitor добавляет много кода, но при использовании дерева каталогов вы получаете гораздо большую гибкость. Чтобы решить ту же проблему, вы можете заменить Files.walk() на:

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

расширение SimpleFileVisitor (для подсчета файлов) и переопределение некоторых методов.

Вы можете:

  • Переопределить метод visitFileFailed, для обработки дела вы не можете получить доступ к файлу по некоторым причинам; (Lukasz_Plawny совет)
  • (необязательно) Переопределите метод 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

Надеюсь, что это поможет.

Ответ 2

Всего несколько непроверенных идей:

1) Запустите приложение с привилегиями root, чтобы начать с:

sudo java -jar myapp.jar

2) Пусть ваше приложение запускает класс-пуск, который запрашивает права root, а затем продолжает работу с остальной частью вашего приложения:

java -jar myapp.jar

Это, в свою очередь, выполняет команду оболочки, но только xterm, которая запрашивает пароль root, а затем продолжает запускать java-программу с правами root:

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 или администратора.

Ответ 3

Нет простого способа изменить разрешения. Java не подходит для этих задач. Есть только некоторые трюки, такие как проверка разрешений при запуске и попытка изменения разрешений через su/sudo, а затем перезапуск приложения или использование Java-gnome. Пожалуйста, прочитайте еще немного: Java: спросите права root на Ubuntu