from - read content txt java
¿Hay alguna forma para que una aplicación Java obtenga permisos de root? (3)
Cuando se ejecuta Files.walk(Paths.get("/var/")).count()
como un usuario sin privilegios, la ejecución puede generar una excepción, ya que hay carpetas dentro de /var/
que necesitan permiso de root para ser recorridas.
No estoy buscando una manera de ejecutar un comando de bash como root (por ejemplo, sudo find /var
), usando Process
, etc.
Solo quiero asegurarme de que Files.walk(Paths.get("/var/")).count()
AccessDeniedException
Files.walk(Paths.get("/var/")).count()
no arroja una 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
Esto es solo un ejemplo. Usando el filter(...)
es posible evitar la excepción. Pero este ejemplo también puede expandirse a otros casos de uso.
En resumen, ¿es posible que las aplicaciones CLI, JavaFX, etc. obtengan permisos de root después de que se hayan ejecutado desde la línea de comandos a través de un método como java -jar app.jar
?
No hay una manera fácil de cambiar los permisos. Java no es bueno en estas tareas. Solo hay algunos trucos como verificar permisos en el inicio e intentar cambiar los permisos a través de su / sudo, luego reiniciar la aplicación o usar Java-gnome. Por favor lee un poco más aquí: Java: pide privilegios de root en Ubuntu
Sólo algunas ideas completamente no probadas:
1) Ejecute su aplicación con privilegios de raíz para comenzar con:
sudo java -jar myapp.jar
2) Permita que su aplicación inicie una clase iniciadora que solicite permisos de root y luego continúe ejecutando el resto de su aplicación:
java -jar myapp.jar
A su vez, esto ejecuta un comando de shell, pero solo un xterm que solicita una contraseña de root y luego continúa ejecutando un programa java con permisos de root:
xterm -e "sudo sh -c ''java -jar /tmp/myrootapp.jar''"
o tal vez use algo de mejor apariencia usando gksudo. Cuidado con el ''
y "
.
Tal vez el myapp.jar
extrae en un directorio temporal . myapp.jar
contiene myrootapp.jar
y, por lo tanto, puede iniciarlo como se describe anteriormente. /tmp
supuesto, /tmp
debe recuperarse desde Java, y preferiblemente debe ser un directorio con un nombre aleatorio al que solo el usuario que ejecuta myapp.jar
tenga acceso para evitar la inyección de myrootapp.jar
.
Multiplataforma
Usted mencionó /var/
yourself, así que asumí que estaba en algún tipo de Linux. Si se supone que esto funciona en varias plataformas, por ejemplo, en Macintosh o Microsoft Windows, primero debe hacer algún tipo de identificación del sistema. Luego, puede aplicar StrategyPattern en el código para manejar las diversas formas de permitir que myrootapp.jar
obtenga permisos de administrador o de administrador.
Si lo que desea es en realidad omitir las rutas donde no tiene acceso, tiene dos enfoques:
Corrientes
En la respuesta a esta pregunta , se explica cómo obtener la secuencia de todos los archivos de un subárbol al que puede acceder.
Pero este ejemplo también puede expandirse a otros casos de uso.
FileVisitor
El uso de FileVisitor
agrega una gran cantidad de código, pero le otorga mucha más flexibilidad al recorrer los árboles de directorios. Para resolver el mismo problema, puede reemplazar Files.walk()
con:
Files.walkFileTree(Path start, FileVisitor<? super Path> visitor);
extendiendo SimpleFileVisitor (para contar los archivos) y anulando algunos métodos.
Usted puede:
-
visitFileFailed
métodovisitFileFailed
, para manejar el caso, no puede acceder a un archivo por alguna razón; (Consejo de Lukasz_Plawny) - (opcional)
preVisitDirectory
métodopreVisitDirectory
,preVisitDirectory
permisos antes de acceder al directorio: si no puede acceder a él, simplemente puede omitir su subárbol (tenga en cuenta que puede acceder a un directorio, pero no a todos sus archivos) ;
por ejemplo 1
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
// you can log the exception ''exc''
return FileVisitResult.SKIP_SUBTREE;
}
por ejemplo 2
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) {
if(!Files.isReadable(dir))
return FileVisitResult.SKIP_SUBTREE;
return FileVisitResult.CONTINUE;
}
Espero eso ayude.