你怎么能弄清楚为什么FIles.isWritable()在Windows上返回false



在我的应用程序中,允许用户偶尔修改他们的音乐文件,当应用程序没有修改文件的权限但用户确信他们已经授予了它完全权限时,我遇到了问题

我发现了Java 7的改进,并编写了此方法来输出权限

public static String displayPermissions(Path path)
{
    StringBuilder sb = new StringBuilder();
    sb.append("File "+path + " permissionsn");
    try
    {
        {
            AclFileAttributeView view = Files.getFileAttributeView(path, AclFileAttributeView.class);
            if (view != null)
            {
                for (AclEntry acl : view.getAcl())
                {
                    sb.append(acl+"n");
                }
            }
        }
        {
            PosixFileAttributeView view = Files.getFileAttributeView(path, PosixFileAttributeView.class);
            if (view != null)
            {
                PosixFileAttributes pfa = view.readAttributes();
                sb.append(":owner:"+pfa.owner().getName()+":group:"+pfa.group().getName()+":"+PosixFilePermissions.toString(pfa.permissions())+"n");
            }
        }
    }
    catch(IOException ioe)
    {
        logger.severe("Unable to read permissions for:"+path.toString());
    }
    return sb.toString();
}

但是对于Windows系统,仍然很难/不可能弄清楚为什么他们没有权限

WARNING: File testdatatest157.dsf permissions
NT AUTHORITYSYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:DENY
BUILTINAdministrators:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:DENY
BUILTINAdministrators:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
NT AUTHORITYSYSTEM:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/DELETE_CHILD/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/WRITE_ACL/WRITE_OWNER/SYNCHRONIZE:ALLOW
BUILTINUsers:READ_DATA/READ_NAMED_ATTRS/EXECUTE/READ_ATTRIBUTES/READ_ACL/SYNCHRONIZE:ALLOW
NT AUTHORITYAuthenticated Users:READ_DATA/WRITE_DATA/APPEND_DATA/READ_NAMED_ATTRS/WRITE_NAMED_ATTRS/EXECUTE/READ_ATTRIBUTES/WRITE_ATTRIBUTES/DELETE/READ_ACL/SYNCHRONIZE:ALLOW

,关于我如何以编程方式找出 isWritable()(或 isReadable())失败的原因的任何建议。

我相信

混淆来自有效权限取决于目录权限和文件权限的事实。

例如,如果用户对文件具有Write权限,但没有对包含目录的Modify权限,则他实际上没有对该文件的写入权限。查看文件和文件夹权限的完整 matix。

要在 Java 中进行检查,您可以使用 FileSystemProvider.checkAccess 方法来检查

假设以下文件和权限(删除所有超出范围的权限以使其更清晰)。权限是使用icacls工具检索的。

c: BUILTINUsers:(OI)(CI)(RX) - read + execute permission
c:bar BUILTINUsers:(RX) - read + execute permission
c:foo BUILTINUsers:(F) - full permission

用于演示的示例代码段。

public class AccessCheckDemo {
    public static void main(String[] args) throws IOException {
        String[] files = {"c:/foo", "c:/bar"};
        for (String file : files) {
            Path path = Paths.get(file);
            System.out.println("check " + path);
            System.out.println("file      Files.isWritable: "
                    + Files.isWritable(path));
            System.out.println("directory Files.isWritable: "
                    + Files.isWritable(path.getParent()));
            System.out.println();
        }
    }
}

输出

check c:foo
file      Files.isWritable: true
directory Files.isWritable: false
check c:bar
file      Files.isWritable: true
directory Files.isWritable: false

即使BUILTINUsers文件上有full permissions c:foo也无法写入此文件,因为目录的权限不允许c:(仅c:上此组的读取+执行权限)。

正如badsamaritan (JDK-7190897)已经提到的,这在Java 7中无法正常工作。

关于如何以编程方式找出 isWritable()(或 isReadable())失败的原因的任何建议

也许这是真正的错误,而不是你的错:

https://bugs.openjdk.java.net/browse/JDK-8034863

http://bugs.java.com/view_bug.do?bug_id=7190897


在谈论Windows权限时,值得一提的是,它们确实有点奇怪(即使Microsoft承认):DENE的优先级高于ALLOW,因此,如果您允许某些用户读取特定文件并拒绝每个人的所有权限,则拒绝会"覆盖"所有内容,并且没有人(包括所有者)无法读取此文件。这就是为什么您不会经常在 ACL 中看到选中的 DENY 权限的原因。

相关内容

最新更新