Java AccessController不接受类';考虑到ProtectionDomain 上下文

Java AccessController不接受类';考虑到ProtectionDomain 上下文,java,security,permissions,securitymanager,sandbox,Java,Security,Permissions,Securitymanager,Sandbox,我正在编写一个Java系统,其中代码在非常严格的沙盒中执行。查询(由一个或多个类组成)在执行期间只能访问一个文件夹(以及文件夹中包含的子文件夹和文件) 我通过在每次查询执行时使用SecurityManager和新的ClassLoader来实施沙箱。使用defineClass在ClassLoader中定义类时,我会传递一个ProtectionDomain,其中包含应授予的文件读取权限 由于并非调用堆栈上的所有对象都具有所需的权限,因此查询中的读取操作在AccessController.doPriv

我正在编写一个Java系统,其中代码在非常严格的沙盒中执行。查询(由一个或多个类组成)在执行期间只能访问一个文件夹(以及文件夹中包含的子文件夹和文件)

我通过在每次查询执行时使用
SecurityManager
和新的
ClassLoader
来实施沙箱。使用
defineClass
ClassLoader
中定义类时,我会传递一个
ProtectionDomain
,其中包含应授予的文件读取权限

由于并非调用堆栈上的所有对象都具有所需的权限,因此查询中的读取操作在
AccessController.doPrivileged(…)
-块中运行

问题
  • 当我直接从
    doPrivileged(…)
    块中调用
    AccessController.checkPermission(…)
    时,它会以静默方式返回
  • 当我调用将请求转发给
    AccessController
    System.getSecurityManager().checkPermission(…)
    时,
    AccessController
    抛出异常
  • 通过
    SecurityManager
    调用
    AccessController
    时,
    ProtectionDomain
    似乎丢失了
  • 受限文件操作(如创建
    java.io.FileReader
    ),直接调用
    SecurityManager
    ,而不是
    AccessController
    当通过
    SecurityManager
    调用
    AccessController
    时,如何让它尊重调用
    doRestricted(…)
    -块的类的
    ProtectionDomain
  • 是否
    SecurityManager
    本身没有所需的权限?因此,通过被夹在特权代码和
    AccessController
    之间的调用堆栈中,会生成一个无特权联合
下面是一个示例部分:

AccessController.doPrivileged(new PrivilegedAction<QueryResult>() {
  public QueryResult run() {
    String location = folderName + "/hello";
    FilePermission p = new FilePermission(location, "read");
    try {
      AccessController.checkPermission(p); // Doesn't raise an exception
      System.out.println("AccessController says OK");
      System.getSecurityManager().checkPermission(p);  // Raises AccessControlException
      System.out.println("SecurityManager says OK");
    } catch (AccessControlException e) {
      System.out.println("### Not allowed to read");
    }
    return null;
  }
});
CoverAccessController.checkPermission(…)
实现可能也很有趣。看起来是这样的:

public void checkPermission(Permission perm) {
  if (Thread.currentThread().getId() == this.masterThread) {
    return;
  } else {
    System.out.println("Asked for permission: "+perm.toString());
  }
  AccessController.checkPermission(perm);
}
它所做的主要是绕过创建它的线程的安全限制



我的文件的内容是标准MacOSX系统的内容。我相信它不包含任何非标准更改。

我认为这里的问题在于如何为
SecurityManager
提供
ProtectionDomain

如果您想自己加载类,并且能够使用SM,那么应该扩展。此类为方法提供了模板:

protected Class defineClass(String name, byte[] b, int off, int len, CodeSource cs) 
在其中,您应该为您的类提供
CodeSource
。然后是另一种方法:

   protected  PermissionCollection getPermissions(CodeSource codesource) 

对于给定的类,它将返回
PermissionCollection
。这就是为动态加载的类实现动态权限的方法。

回答我自己的问题时,我感到有点尴尬,但我找到了正确的解决方案,并且认为将其添加到此处才是正确的,因此,为了防止将来有人在这个问题上遇到问题,将对其进行记录

TL;博士: 我的自定义没有正确的权限。由于它位于调用
doPrivileged(…)
-块的类和之间的调用堆栈上,所以特权的交集根本就不是特权

长版本 Java安全模型的工作原理如下。当验证是否允许类调用方法时,它会从调用堆栈的顶部向底部查看权限。如果callstack中的每个条目都有权限,则允许该操作

这是一个任意的例子,一切都很顺利:

+-----------+-------------------+-----------------------+
| Callstack | Class permissions | Permissions in effect |
+-----------+-------------------+-----------------------+
| Some      | {Read,Write}      | {Read}                |
| Other     | {Read}            | {Read}                |
+-----------+-------------------+-----------------------+
现在,在我的问题中,调用堆栈中的较低层根本没有权限。 因此,我们最终得到这样一幅图片,上面的
查询
实际上没有权限

+-----------+-------------------+-----------------------+
| Callstack | Class permissions | Permissions in effect |
+-----------+-------------------+-----------------------+
| Query     | {Read}            | {}                    |
| Other     | {}                | {}                    |
+-----------+-------------------+-----------------------+
您可以通过使用
doPrivileged(…)
-块绕过这个问题。这允许通过调用堆栈的权限搜索在调用特权操作的条目处结束:

+-----------+-------------------+-----------------------+
| Callstack | Class permissions | Permissions in effect |
+-----------+-------------------+-----------------------+
| Query     | {Read}            | {Read}                |
| Other     | {}                | {}                    |
+-----------+-------------------+-----------------------+
这就是为什么当我从查询中调用
AccessController.checkPermission(…)
时,一切都正常工作的原因。毕竟,它确实拥有正确的权限。(Un)幸运的是,JavaAPI(为了向后兼容)总是调用。就我而言,他们根本没有特权。由于它实际上位于进行特权调用的查询与之间的调用堆栈上,因此产生的净权限为无:

+-----------------+-------------------+-----------------------+
|    Callstack    | Class permissions | Permissions in effect |
+-----------------+-------------------+-----------------------+
| SecurityManager | {}                | {}                    |
| Query           | {Read}            | {Read}                |
| Other           | {}                | {}                    |
+-----------------+-------------------+-----------------------+
解决方案 解决方案是为用户提供一组基本权限。因此,授予查询的权限确实是所需的权限:

+-----------------+---------------------+-----------------------+
|    Callstack    |  Class permissions  | Permissions in effect |
+-----------------+---------------------+-----------------------+
| SecurityManager | {Read,Write,Delete} | {Read}                |
| Query           | {Read}              | {Read}                |
| Other           | {}                  | {}                    |
+-----------------+---------------------+-----------------------+

呸!那真是太多了!希望这对其他人有用:)

为了完整性,请插入此权限的策略文件条目。还可以尝试使用SecurityManager.checkPermission插入AccessController。checkPermission@fatfredyy在上面发布了我的java.policy文件。使用SecurityManager.checkPermission而不是AccessController.checkPermission非常好。我更改了它,现在我的支票也抛出了AccessControlException。通过SecurityManager时权限似乎丢失了?这完全改变了我的问题。我会相应地更新它。谢谢谢谢@fatfredyy,我现在根据您的评论更改了问题。事实证明,现在的问题完全不同了。从我所看到的情况来看,您没有修改策略文件。。。如何为代码提供许可?您的代码是从ext java lib path还是从系统java lib path加载的?出于所有目的,我将这些类作为字节数组传递给我。然后,在我的类加载器中,我调用
defineClass(名称、二进制、保护域)
。保护域也由类加载器创建,并且完全包含我想要的权限集
+-----------------+---------------------+-----------------------+
|    Callstack    |  Class permissions  | Permissions in effect |
+-----------------+---------------------+-----------------------+
| SecurityManager | {Read,Write,Delete} | {Read}                |
| Query           | {Read}              | {Read}                |
| Other           | {}                  | {}                    |
+-----------------+---------------------+-----------------------+