Как изменить права доступа к файлам в Java с помощью библиотеки NIO в Windows 7

Я пытаюсь написать код, который начинается с объекта Path, предназначенного для определенного файла, и делает так, чтобы у владельца файла больше не было разрешений на его перемещение, удаление или изменение, но они все еще могут его читать. Также необходимо убедиться, что это можно отменить, а также поддерживать неограниченный доступ для администраторов в любое время.

Одна из моих основных проблем заключается в том, что я не могу понять, как получить имена профилей пользователей и имена групп, которые есть в системе.

Подробное объяснение было бы фантастическим.


person JereTheJuggler    schedule 09.06.2016    source источник
comment
Я действительно понял, как получить более или менее желаемый результат. Единственное, в чем я до сих пор не уверен, - это действительно ли возможно отменить разрешение пользователя на перемещение файла, и если это возможно, то как.   -  person JereTheJuggler    schedule 12.06.2016
comment
Это довольно сложно, позвольте мне показать вам, как это сделать. По крайней мере, я думаю, что это работает, я единственный пользователь и администратор, поэтому я не могу его протестировать.   -  person JD9999    schedule 12.06.2016


Ответы (1)


Класс File может установить файл для чтения, записи и выполнения. Чтобы получить его пользователем, вам необходимо использовать NIO.

Класс Files и NIO используют PosixFilePermissions, который устанавливает разрешения для файлов и трех групп: пользователя, владельца и группы. В Windows администраторы будут в группе, а также в системе.

Для его перемещения нам понадобится собственный SecurityManager. При перемещении файлов NIO использует разрешение на запись. Итак, наш SecurityManager должен изменить разрешение на запись. См. Мой код ниже в качестве примера.

p.s. хотя FileSystemsProvider - это WindowsFileSystemProvider, он возвращается FileSystemProviders.getProvider (или аналогичным методом). Возможно, что файл rt.jar отличается для каждой загруженной ОС, но если вы работаете в Windows, вы можете предположить, что это правильно.

PathRestrictor.java

package Testers;

import java.io.IOException;
import java.net.URI;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.AccessMode;
import java.nio.file.CopyOption;
import java.nio.file.DirectoryStream;
import java.nio.file.DirectoryStream.Filter;
import java.nio.file.FileStore;
import java.nio.file.FileSystem;
import java.nio.file.Files;
import java.nio.file.LinkOption;
import java.nio.file.OpenOption;
import java.nio.file.Path;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileAttributeView;
import java.nio.file.attribute.PosixFilePermission;
import java.nio.file.spi.FileSystemProvider;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import sun.nio.fs.WindowsFileSystemProvider;


public class PathRestrictor extends FileSystemProvider{

    boolean canRead;
    boolean canWrite;
    boolean canMove; //This is the tricky one
    boolean canOpen;
    private Path path;
    WindowsFileSystemProvider provider = new WindowsFileSystemProvider();

    public PathRestrictor(Path p){
        path = p;
        canRead = true;
        canWrite = true;
        canOpen = true;
    }

    public void setExecuteable(boolean executable){
        canOpen = executable;
        try {
            Files.setPosixFilePermissions(path, getPerms());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setReadable(boolean readable){
        canRead = readable;
        try {
            Files.setPosixFilePermissions(path, getPerms());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setWriteable(boolean writeable){
        canWrite = writeable;
        try {
            Files.setPosixFilePermissions(path, getPerms());
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public void setMoveable(boolean moveable){
        canMove = moveable;
        MovementSecurityManager manager = new MovementSecurityManager();
        if(!moveable)manager.unMoveablePaths.add(path.toString());
        else manager.unMoveablePaths.remove(path.toString());
        System.setSecurityManager(manager);


    }

    private Set<PosixFilePermission> getPerms() {
        Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
        perms.add(PosixFilePermission.GROUP_EXECUTE);
        perms.add(PosixFilePermission.GROUP_READ);
        perms.add(PosixFilePermission.GROUP_WRITE);
        if(canRead){
            perms.add(PosixFilePermission.OTHERS_READ);
            perms.add(PosixFilePermission.OWNER_READ);
        }
        if(canWrite){
            perms.add(PosixFilePermission.OTHERS_WRITE);
            perms.add(PosixFilePermission.OWNER_WRITE);
        }
        if(canOpen){
            perms.add(PosixFilePermission.OTHERS_EXECUTE);
            perms.add(PosixFilePermission.OWNER_EXECUTE);
        }
        return perms;
    }

    @Override
    public void checkAccess(Path path, AccessMode... modes) throws IOException {
        provider.checkAccess(path, modes);
    }

    @Override
    public void copy(Path source, Path target, CopyOption... options)
            throws IOException {
        // TODO Auto-generated method stub
        provider.copy(source, target, options);

    }

    @Override
    public void createDirectory(Path dir, FileAttribute<?>... attrs)
            throws IOException {
        provider.createDirectory(dir, attrs);
    }

    @Override
    public void delete(Path path) throws IOException {
        provider.delete(path);
    }

    @Override
    public <V extends FileAttributeView> V getFileAttributeView(Path path,
            java.lang.Class<V> type, LinkOption... options) {
        return provider.getFileAttributeView(path, type, options);
    }

    @Override
    public FileStore getFileStore(Path path) throws IOException {
        return provider.getFileStore(path);
    }

    @Override
    public FileSystem getFileSystem(URI uri) {
        return provider.getFileSystem(uri);
    }

    @Override
    public Path getPath(URI uri) {
        return provider.getPath(uri);
    }

    @Override
    public String getScheme() {
        return provider.getScheme();
    }

    @Override
    public boolean isHidden(Path path) throws IOException {
        return provider.isHidden(path);
    }

    @Override
    public boolean isSameFile(Path path, Path path2) throws IOException {
        return path.toString().equals(path2.toString());
    }

    @Override
    public void move(Path source, Path target, CopyOption... options)
            throws IOException {
            MovementSecurityManager manager = new MovementSecurityManager();
            manager.isMoving = true;
            System.setSecurityManager(manager);
            provider.move(source, target, options);
    }

    @Override
    public SeekableByteChannel newByteChannel(Path path,
            Set<? extends OpenOption> options, FileAttribute<?>... attrs)
            throws IOException {
        return provider.newByteChannel(path, options, attrs);
    }

    @Override
    public DirectoryStream<Path> newDirectoryStream(Path dir,
            Filter<? super Path> filter) throws IOException {
        return provider.newDirectoryStream(dir, filter);
    }

    @Override
    public FileSystem newFileSystem(URI uri, Map<String, ?> env)
            throws IOException {
        return provider.newFileSystem(uri, env);
    }

    @Override
    public <A extends BasicFileAttributes> A readAttributes(Path path,
            java.lang.Class<A> type, LinkOption... options) throws IOException {
        return provider.readAttributes(path, type, options);
    }

    @Override
    public Map<String, Object> readAttributes(Path path, String attributes,
            LinkOption... options) throws IOException {
        return provider.readAttributes(path, attributes, options);
    }

    @Override
    public void setAttribute(Path path, String attribute, Object value,
            LinkOption... options) throws IOException {
        provider.setAttribute(path, attribute, value, options);

    }

}

MovementSecurityManager.java

package Testers;

import java.util.HashSet;
import java.util.Set;

public class MovementSecurityManager extends SecurityManager {

    public Set<String> unMoveablePaths = new HashSet<String>();
    public boolean isMoving = true;

    public void checkWrite(String path){
        if(unMoveablePaths.contains(path) && isMoving) throw new SecurityException("Cannot move file!");
        else super.checkWrite(path);
    }

}
person JD9999    schedule 12.06.2016
comment
Это будет работать только один раз и только для перемещений, инициированных текущей JVM. - person user207421; 12.06.2016
comment
Я получаю только инициированный текущей JVM, но что вы имеете в виду, что он работает только один раз? - person JD9999; 12.06.2016
comment
Насколько я знаю, я ничего не могу сделать, чтобы исправить эту проблему. - person JD9999; 12.06.2016