使用java设置ACL在子文件夹上失败(缺少继承)

时间:2014-02-03 10:08:20

标签: java file-permissions

以下代码为群组G-Test的文件夹“\\ myShare \ Folder1 \”设置“读取”权限:

String gName="G-Test";
AclEntryPermission[] aeps=new AclEntryPermission[]{
        AclEntryPermission.READ_DATA,
        AclEntryPermission.READ_ATTRIBUTES,
        AclEntryPermission.READ_NAMED_ATTRS,
        AclEntryPermission.READ_ACL,
        AclEntryPermission.SYNCHRONIZE
    };      
Path p = FileSystems.getDefault().getPath(new File("\\\\myShare\\Folder1\\").getPath());
AclFileAttributeView view = Files.getFileAttributeView(p, AclFileAttributeView.class);
Set<AclEntryPermission> set = EnumSet.noneOf(AclEntryPermission.class);
for (AclEntryPermission acp: aeps) set.add(acp);
AclEntry.Builder b= AclEntry.newBuilder();
b.setType(AclEntryType.ALLOW);
b.setPermissions(set);
b.setPrincipal(FileSystems.getDefault().getUserPrincipalLookupService().lookupPrincipalByName(gName));
b.setFlags(new AclEntryFlag[]{AclEntryFlag.FILE_INHERIT,AclEntryFlag.DIRECTORY_INHERIT});       
List<AclEntry> acl = view.getAcl();
acl.add(b.build());
view.setAcl(acl);

这适用于folder1按预期方式。但是在Folder2(子文件夹:\\ myShare \ Folder1 \ Folder2)上,ACL不会被继承。使用Windows GUI查看Folder2中缺少继承的ACL。

当使用Windows更改ACL以获取Folder1中的另一个组/权限时,我可以在folder2上看到先前缺少的权限。或者在创建新的子文件夹时,ACL是正确的继承。

上面的代码有问题吗?我想在folder1上设置Read-Permissions,它继承了所有子文件夹和文件。

代码在Windows 8.1 PC上运行,共享是Windows 2008 R2文件 - 群集

1 个答案:

答案 0 :(得分:2)

您的代码运行正常。我有一个几乎相同的结构来设置我的环境中的权限,它也适用于那里。问题是修改权限时Folder2已存在。某些Windows API调用会在目录树中传播更改,而有些则不会(请参阅this question的答案)。 JRE必须使用其中之一。我想,你必须自己走树去传播这些变化。但是,如果在设置权限后创建Folder2,那么它将具有从顶部继承的权限(至少它是在我的上面)。

编辑: 我更多地考虑了这个问题,并认为我将来也可能需要走树。由于我们在这里谈论Java 7,我寻找一种比以前更容易走树的方法。事实证明,Files.walkFileTree()方法只是票证!我想出了这个,虽然我会分享它:

private void grantAccess(final UserPrincipal user, Path folder) {
    try {
        Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {              
            @Override
            public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
                grant(dir);
                return FileVisitResult.CONTINUE;
            }

            @Override
            public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
                grant(file);
                return FileVisitResult.CONTINUE;
            }

            private void grant(Path p) throws IOException {
                AclFileAttributeView view = Files.getFileAttributeView(p, AclFileAttributeView.class);
                AclEntry accessEntry = createAccessACLEntry(user);
                List<AclEntry> acl = view.getAcl();
                acl.add(0, accessEntry); // insert at head in case there are any DENY entries
                view.setAcl(acl);
            }

            private AclEntry createAccessACLEntry(UserPrincipal user) {
                AclEntry entry = AclEntry
                        .newBuilder()
                        .setType(AclEntryType.ALLOW)
                        .setPrincipal(user)
                        .setPermissions(AclEntryPermission.DELETE_CHILD,
                                AclEntryPermission.WRITE_NAMED_ATTRS,
                                AclEntryPermission.EXECUTE,
                                AclEntryPermission.WRITE_DATA,
                                AclEntryPermission.WRITE_ATTRIBUTES,
                                AclEntryPermission.READ_ATTRIBUTES,
                                AclEntryPermission.APPEND_DATA,
                                AclEntryPermission.READ_DATA,
                                AclEntryPermission.READ_NAMED_ATTRS,
                                AclEntryPermission.READ_ACL,
                                AclEntryPermission.SYNCHRONIZE,
                                AclEntryPermission.DELETE)
                        .setFlags(AclEntryFlag.FILE_INHERIT,
                                AclEntryFlag.DIRECTORY_INHERIT)   
                        .build();
                return entry;
            }
        });
    } catch (IOException e) {
        throw new IllegalStateException("Unable to grant access for " + folder.toString() + " to " + user.getName(), e);
    }
}

您必须覆盖visitFile()和preVisitDirectory(),以便更改文件和文件夹的权限,但您可以将postVisitDirectory()替换为preVisitDirectory()。