我正在尝试实现自定义java.security.Permission
类型,应该在运行时检查(因此没有策略文件,但在代码中)。此检查由java.security.Policy
完成。我知道我应该为此实现我自己的java.security.PolicySpi
。
我找不到有关如何初始化和使用PolicySpi的任何解释,还是有更好的方法来执行此操作?
答案 0 :(得分:3)
在您的问题中,您声明您希望使用java.security.Policy
检查权限,但不使用spi.policy
文件。
从PolicySpi API,您可以看到PolicySpi对象包含4种方法:
但是,您可能不需要 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
的替代。
创作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;
});
}
}
创作由提供商封装的唯一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;
}
}
编写服务描述符生成的实际服务(本例中为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;
}
}
静态注册提供商,方法是修改security.provider.n
中的JAVA_HOME/lib/security/java.security
属性,或通过java.security.Security.addProvider(Provider)
/ java.security.Security.insertProviderAt(Provider, int)
以编程方式注册。
替换默认的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
}
}
有更好的方法吗?
肯定有一种较少涉及的方式,只要应用程序和策略之间的紧密耦合不会让你感觉太糟糕:只需直接子类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();
}
}