【问题标题】:Programmatically grant Permissions without using policy file在不使用策略文件的情况下以编程方式授予权限
【发布时间】:2012-07-31 10:20:57
【问题描述】:

如何在不使用策略文件的情况下以编程方式将AllPermissions 授予RMI 应用程序?

更新:

经过一番研究,我编写了这个自定义策略类并通过Policy.setPolicy(new MyPolicy()) 安装它。

现在我收到以下错误:

无效的权限:(java.io.FilePermission \C:\eclipse\plugins\org.eclipse.osgi_3.7.0.v20110613.jar 读取

class MyPolicy extends Policy {

    @Override
    public PermissionCollection getPermissions(CodeSource codesource) {
        return (new AllPermission()).newPermissionCollection();
    }

}

【问题讨论】:

    标签: java permissions rmi policyfiles


    【解决方案1】:

    根据 @EJP 的建议,我使用-Djava.security.debug=access 进行了调试,并在策略文件中找到了所有需要的权限:

    grant { 权限 java.net.SocketPermission "*:1024-", "connect, 解决"; };

    grant { 权限 java.util.PropertyPermission "*", "read, write"; };

    grant { 权限 java.io.FilePermission "", "read"; };

    但因为我不想创建策略文件,所以我找到了一种通过扩展 java.security.Policy 类并在我的应用程序启动时使用 Policy.setPolicy(new MinimalPolicy()); 设置策略来以编程方式复制此文件的方法

    public class MinimalPolicy extends Policy {
    
        private static PermissionCollection perms;
    
        public MinimalPolicy() {
            super();
            if (perms == null) {
                perms = new MyPermissionCollection();
                addPermissions();
            }
        }
    
        @Override
        public PermissionCollection getPermissions(CodeSource codesource) {
            return perms;
        }
    
        private void addPermissions() {
            SocketPermission socketPermission = new SocketPermission("*:1024-", "connect, resolve");
            PropertyPermission propertyPermission = new PropertyPermission("*", "read, write");
            FilePermission filePermission = new FilePermission("<<ALL FILES>>", "read");
    
            perms.add(socketPermission);
            perms.add(propertyPermission);
            perms.add(filePermission);
        }
    
    }
    

    class MyPermissionCollection extends PermissionCollection {
    
        private static final long serialVersionUID = 614300921365729272L;
    
        ArrayList<Permission> perms = new ArrayList<Permission>();
    
        public void add(Permission p) {
            perms.add(p);
        }
    
        public boolean implies(Permission p) {
            for (Iterator<Permission> i = perms.iterator(); i.hasNext();) {
                if (((Permission) i.next()).implies(p)) {
                    return true;
                }
            }
            return false;
        }
    
        public Enumeration<Permission> elements() {
            return Collections.enumeration(perms);
        }
    
        public boolean isReadOnly() {
            return false;
        }
    
    }
    

    【讨论】:

    • 从 Java8 开始,您可以将 implies 简化为 return perms.stream().anyMatch(it-&gt;it-implies(p));
    【解决方案2】:

    因为你的

    new AllPermission()).newPermissionCollection()

    被Java视为不可变的(为什么要向已经允许所有权限的集合添加权限?),并且因为Java会尝试向集合添加权限。这就是错误消息的来源 - Java 尝试将 java.io.FilePermission 添加到您的 AllPermission。

    相反,这样做:

    class MyPolicy extends Policy {
        @Override
        public PermissionCollection getPermissions(CodeSource codesource) {
            Permissions p = new Permissions();
            p.add(new PropertyPermission("java.class.path", "read"));
            p.add(new FilePermission("/home/.../classes/*", "read"));
            ... etc ...
            return p;
        }
    }
    

    【讨论】:

    • 其实你的推理有点正确。但这并不完全正确:检查 AllPermissions 的源代码,默认情况下,(new AllPermission()).newPermissionCollection() 返回一个始终返回 false 的权限集合。直到您向其添加 AllPermission 实例为止。
    【解决方案3】:

    不要安装 SecurityManager。仅当您使用代码库功能时才需要它,并且如果您需要适当的 .policy 文件,

    【讨论】:

    • 我必须使用代码库功能。所以我确实需要它。我希望用包含AllPermissionCollection 的自定义java.security.Policy 替换策略文件。它可以这样工作吗?以及需要覆盖什么才能使其工作?
    • @AdelBoutros 如果您正在使用代码库功能,您肯定不想授予 AllPermission。您将从另一个来源运行代码。您需要构建一个适当的 .policy 文件,该文件准确授予您认为下载的代码应该需要的权限,而不是其他权限。您可以通过 -Djava.security.debug=access,failure 中的一些 helpmfr 来确定这一点。
    • 我已经知道如何创建策略文件了。这不是我想要的,因为我的应用程序是一个 Eclipse 插件,因此您不能将策略文件添加到单个 eclipse-plugin,您需要将其添加到客户端很难找到的 eclipse.ini接受
    • @AdelBoutros 你别无选择。没有办法做你想做的事。无论如何,我建议您的客户会发现更难接受一个 RMI 产品,如果可能的话,它会禁用所有设计到 RMI 中的安全功能,幸运的是事实并非如此。您应该做的是给 client 定义权限的机会,而不是试图回避问题并破坏 Java 安全模型。
    • 目前,我创建了自己的SecurityManager 并覆盖了所有checkPermissions 方法,让它们什么都不做。但我想知道这里有什么风险? (我试过谷歌搜索,但没有找到太多信息)
    【解决方案4】:

    短解决方案

    将更新后的解决方案扩展到:

    public class MyPolicy extends Policy
    {
        @Override
        public PermissionCollection getPermissions(CodeSource codesource)
        {
            Permissions p = new Permissions();
            p.add(new AllPermission());
            return p;
        }
    }
    

    考虑一下,Policy.getPermissions() 必须始终返回一个可变 PermissionCollection

    返回: ...如果支持此操作,则返回的权限集必须是新的可变实例,并且必须支持异构权限类型...

    这个解决方案已经可以工作了,因为它在每次调用 Policy.getPermissions(ProtectionDomain) 时添加了一个 AllPermission 对象,它引用了Policy.getPermissions(CodeSource)

    清洁解决方案

    但是有一个更简洁的解决方案,它不会跟踪任何不必要的其他权限,因为 AllPermissions 已经允许几乎所有内容。

    public class MyPolicy extends Policy
    {
        private static class AllPermissionsSingleton extends PermissionCollection
        {
            private static final long serialVersionUID = 1L;
            private static final Vector<Permission> ALL_PERMISSIONS_VECTOR = new Vector<Permission>(Arrays.asList(new AllPermission()));
    
            @Override
            public void add(Permission permission)
            {
            }
    
            @Override
            public boolean implies(Permission permission)
            {
                return true;
            }
    
            @Override
            public Enumeration<Permission> elements()
            {
                return ALL_PERMISSIONS_VECTOR.elements();
            }
    
            @Override
            public boolean isReadOnly()
            {
                return false;
            }
        }
    
        private static final AllPermissionsSingleton ALL_PERMISSIONS_SINGLETON = new AllPermissionsSingleton();
    
        @Override
        public PermissionCollection getPermissions(CodeSource codesource)
        {
            return ALL_PERMISSIONS_SINGLETON;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-04-08
      • 1970-01-01
      • 2017-08-07
      • 2023-03-08
      • 2018-03-18
      • 2018-01-18
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多