如何使用自定义PolicySpi

时间:2014-02-25 14:10:21

标签: java security permissions policy

我正在尝试实现自定义java.security.Permission类型,应该在运行时检查(因此没有策略文件,但在代码中)。此检查由java.security.Policy完成。我知道我应该为此实现我自己的java.security.PolicySpi

我找不到有关如何初始化和使用PolicySpi的任何解释,还是有更好的方法来执行此操作?

3 个答案:

答案 0 :(得分:3)

检查权限

在您的问题中,您声明您希望使用java.security.Policy检查权限,但不使用spi.policy文件。

PolicySpi API,您可以看到PolicySpi对象包含4种方法:

  1. engineGetPermissions(CodeSource codesource)
  2. engineGetPermissions(ProtectionDomain domain)
  3. engineImplies(ProtectionDomain domain, Permission permission)
  4. engineRefresh()
  5. 但是,您可能不需要 PolicySpi ,因为有更简单的方法可以检查权限。

    请参阅:

    由于您尚未指定您将授予的权限类型,因此我认为这是对java.security.CodeSource对象的权限。

    检查文件的所有当前权限:

    public static void main(String[] args) {
    
        CodeSource source;
    
        try {
          source = new CodeSource(new URL("file:/c:/*"), (java.security.cert.Certificate[]) null);
    
          Policy policy = Policy.getPolicy();
          System.out.println(policy.getPermissions(source));
    
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    

    SecurityManager checkPermission()的一个很好的例子是this tutorial

    要检查特定的FilePermission,您可以使用:

    FilePermission perm = new FilePermission("path/file", "read");
    AccessController.checkPermission(perm);
    

    授予权限

    可以使用java.lang.RuntimePermission在运行时授予权限。

    有关如何为文件授予权限的其他示例,建议您阅读以下内容:


    那应该给你带来很长的路要走!祝你好运!

答案 1 :(得分:0)

previous答案列出了使用PolicySpi(以及更常见的自定义Policy实施)的替代方法。这个答案将提供一个简单的例子,说明PolicySpi实现如何实际用作系统默认Policy的替代。

  1. 创作JCA Provider

    package com.example;
    
    import java.security.AccessController;
    import java.security.PrivilegedAction;
    import java.security.Provider;
    
    public final class TestProvider extends Provider {
    
        private static final long serialVersionUID = 5544432861418770903L;
    
        public TestProvider() {
            super("TestProvider", 1, "TestProvider 1.0");
            AccessController.doPrivileged((PrivilegedAction<Void>) () -> {
                putService(new TestPolicySpiService(this));
                return null;
            });
        }
    
    }
    
  2. 创作由提供商封装的唯一Service描述符。

    package com.example;
    
    import java.security.Policy.Parameters;
    import java.security.PolicySpi;
    import java.security.Provider;
    import java.security.Provider.Service;
    import java.util.Collections;
    
    final class TestPolicySpiService extends Service {
    
        TestPolicySpiService(Provider p) {
            super(p, "Policy", "TestPolicy", PolicySpi.class.getName(), Collections.emptyList(), Collections.emptyMap());
        }
    
        @Override
        public PolicySpi newInstance(Object constructorParameter) {
            Parameters policyParams = null;
            if (constructorParameter instanceof Parameters) {
                policyParams = (Parameters) constructorParameter;
            }
            return new TestPolicySpi(policyParams);
        }
    
        @Override
        public boolean supportsParameter(Object parameter) {
            return parameter instanceof Parameters;
        }
    
    }
    
  3. 编写服务描述符生成的实际服务(本例中为PolicySpi实现)。

    package com.example;
    
    import java.security.Permission;
    import java.security.Policy.Parameters;
    import java.security.PolicySpi;
    import java.security.ProtectionDomain;
    
    final class TestPolicySpi extends PolicySpi {
    
        TestPolicySpi(Parameters policyParams) {}
    
        @Override
        protected boolean engineImplies(ProtectionDomain domain, Permission permission) {
            // deny unconditionally
            return false;
        }
    
    }
    
  4. 静态注册提供商,方法是修改security.provider.n中的JAVA_HOME/lib/security/java.security属性,或通过java.security.Security.addProvider(Provider) / java.security.Security.insertProviderAt(Provider, int)以编程方式注册。

  5. 替换默认的Policy

    package com.example;
    
    import java.security.NoSuchAlgorithmException;
    import java.security.Policy;
    
    public class Main {
    
        public static void main(String... args) throws NoSuchAlgorithmException {
            // the following assumes that the provider has been statically registered
            Policy.setPolicy(Policy.getInstance("TestPolicy", null));
            System.setSecurityManager(new SecurityManager());
    
            // test
            System.out.println(System.getProperty("user.home")); // should raise AccessControlException
        }
    
    }
    
  6. 有更好的方法吗?

    肯定有一种较少涉及的方式,只要应用程序和策略之间的紧密耦合不会让你感觉太糟糕:只需直接子类Policy并传递你的实例实施到Policy.setPolicy(Policy)

    <小时/> 进一步阅读:

答案 2 :(得分:0)

从Java 6开始,PolicySpi的默认实现为sun.security.provider.PolicySpiFile。您可以从PolicySpiFile的{​​{3}}中得到启发:

package sun.security.provider;

import java.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Policy;
import java.security.PolicySpi;
import java.security.ProtectionDomain;
import java.security.URIParameter;

import java.net.MalformedURLException;

/**
 * This class wraps the PolicyFile subclass implementation of Policy
 * inside a PolicySpi implementation that is available from the SUN provider
 * via the Policy.getInstance calls.
 *
 */
public final class PolicySpiFile extends PolicySpi {

    private PolicyFile pf;

    public PolicySpiFile(Policy.Parameters params) {

        if (params == null) {
            pf = new PolicyFile();
        } else {
            if (!(params instanceof URIParameter)) {
                throw new IllegalArgumentException
                        ("Unrecognized policy parameter: " + params);
            }
            URIParameter uriParam = (URIParameter)params;
            try {
                pf = new PolicyFile(uriParam.getURI().toURL());
            } catch (MalformedURLException mue) {
                throw new IllegalArgumentException("Invalid URIParameter", mue);
            }
        }
    }

    protected PermissionCollection engineGetPermissions(CodeSource codesource) {
        return pf.getPermissions(codesource);
    }

    protected PermissionCollection engineGetPermissions(ProtectionDomain d) {
        return pf.getPermissions(d);
    }

    protected boolean engineImplies(ProtectionDomain d, Permission p) {
        return pf.implies(d, p);
    }

    protected void engineRefresh() {
        pf.refresh();
    }
}