java - 如何找出 FIles.isWritable() 在 Windows 上返回 false 的原因

标签 java windows file security

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

我发现了 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())失败原因的任何建议。

最佳答案

我认为造成困惑的原因是有效权限取决于目录权限和文件权限。

如果用户有例如文件的写入权限,但没有包含目录的修改权限,他实际上没有对该文件的写入权限。查看 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

用于演示的示例片段。

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 拥有完全权限,他们也无法写入此文件,因为目录 c:\ 的权限不允许这样做(该组在 c:\ 上只有读取 + 执行权限)。

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

关于java - 如何找出 FIles.isWritable() 在 Windows 上返回 false 的原因,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35082228/

相关文章:

java - 使用 StructuredQueryBuilder 指定动态排序顺序

java - 使用 Lucene 搜索带有空格的术语

单击通知区域图标 Windows 的 C++ 事件处理

c++ - 如何使控制台程序没有控制台窗口

c - 从二进制文件写入和读取整数数组

C++在类函数中和类外写入文件

java - 如何从匿名类内部访问封闭类实例变量?

Java同步文件写入

c++ - 如何生成唯一的文件名或路径?

C++/CX - DataReader 越界异常