【问题标题】:How can you work out why FIles.isWritable() returns false on Windows你怎么知道为什么 FIles.isWritable() 在 Windows 上返回 false
【发布时间】:2016-01-29 10:30:06
【问题描述】:

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

我发现了 Java 7 的改进并写了这个方法来输出权限

public static String displayPermissions(Path path)
{
    StringBuilder sb = new StringBuilder();
    sb.append("File "+path + " permissions\n");
    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 testdata\test157.dsf permissions
NT AUTHORITY\SYSTEM: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
BUILTIN\Administrators: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
BUILTIN\Administrators: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 AUTHORITY\SYSTEM: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
BUILTIN\Users:READ_DATA/READ_NAMED_ATTRS/EXECUTE/READ_ATTRIBUTES/READ_ACL/SYNCHRONIZE:ALLOW
NT AUTHORITY\Authenticated 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())失败原因的任何建议。

【问题讨论】:

  • 看起来有点奇怪的是。 BUILTIN\Administrators 拥有 DENYALLOW 的相同权限。
  • 这只是一个例子,但我手动将权限设置为拒绝但似乎无法删除现有的允许权限,坦率地说我发现 Windows 权限难以理解。

标签: java windows file security


【解决方案1】:

我认为混淆来自于有效权限取决于目录权限和文件权限这一事实。

如果用户有例如文件的Write 权限,但不是包含目录的Modify 权限,他实际上没有对该文件的写入权限。查看File and folder permissions的完整矩阵。

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

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

c:\ BUILTIN\Users:(OI)(CI)(RX) - read + execute permission

c:\bar BUILTIN\Users:(RX) - read + execute permission

c:\foo BUILTIN\Users:(F) - full permission

用于演示的示例 sn-p。

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

即使BUILTIN\Users 在文件c:\foo 上有full permissions,他们也无法写入该文件,因为目录c:\ 的权限不允许它(c:\ 上该组只有读取+执行权限) .

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

【讨论】:

  • 这很有趣,我没有使用这种方法,但我已经在使用 Files.isReadable(),Files.isWritable() 似乎无论如何都在使用它。但是从上面的示例中,您似乎是在说它可以为文件的 isWritable() 返回 true,即使该文件可能不可写,因为您在包含文件夹中没有足够的权限。如果您实际上没有修改它的权限,我想要的是它返回 false ,但不写文件夹的权限只是意味着您需要它在文件夹中创建新文件而不是编辑文件夹中的文件?顺便说一句,我已经在使用 Java 8。
  • @PaulTaylor 你说得对,Files.isReadable()Files.isWritable()FileSystemProvider.checkAccess() 方法的包装。如果文件系统正在使用 ACL,那么您需要自上而下地阅读它们。使用第一个匹配条目。如果用户无权写入特定目录中的文件,则不检查包含文件的权限。例如,这不同于默认的 Linux 用户/组/其他模式。如果用户对目录没有写权限,这意味着他不能创建/删除文件。但如果权限允许,他仍然可以修改文件。
【解决方案2】:

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

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

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

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


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

【讨论】:

  • 谢谢你,这是关于 DENY 的非常有用的一点,第二个错误非常有趣,因为我还没有更新到 java 8 的错误修复版本,这很可能会解决一些问题。但我的问题并不是“为什么我没有权限”,而是“给定一组 Windows 权限,我如何解码它们以为用户提供有效权限”
  • 好的,我想我回答了问题的另一半。无论如何,祝这个话题好运:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-08-23
  • 2021-08-18
  • 2016-08-07
  • 2020-02-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多