Java 安全管理器 @Override public void checkPermission(Permission perm)

6
我正在构建一个SWING应用程序,还需要编写自定义的SecurityManager。如果我编写一个继承SecurityManager的空类,如下所示:
public class Sandbox extends SecurityManager {}

它正常工作,意味着GUI呈现正确,并且所有特权(如I/O)都被撤销。 然而,我需要自定义checkPermission方法,但每当我覆盖它时,什么都不起作用了... 为什么即使像这样的东西也不能工作?

public class Sandbox extends SecurityManager {
  @Overide
  public void checkPermission(Permission perm) {
    super.checkPermission(perm);
  }
}

更新:一个非常基础的示例,展示了这个问题。
public static void main(String[] args) {

    System.setSecurityManager(new SecurityManager() {
        @Override
        public void checkPermission(Permission p) {
            if (some_condition_here) {
              // Do something here
            } else {
              // Resort to default implementation
              super.checkPermission(p);
            }
        }
    });

    new JFrame().setVisible(true);

}

移除“checkPermission”方法后,应用程序可以正常工作,但我真的无法理解这个。


为了更快得到帮助,请发布一个SSCCE - Andrew Thompson
我已经更新了问题,并提供了一个示例。 - Flavio
这也可能很有趣 http://docs.oracle.com/javase/7/docs/technotes/guides/security/smPortGuide.html - mike
好的 - 我被难住了,抱歉.. - Andrew Thompson
2个回答

1
权限是基于堆栈上所有代码授予的。所有调用者必须具备所需权限。如果您覆盖该方法并调用超类方法,则您的代码也位于堆栈上,这意味着您的代码库(其中包含您自定义的SecurityManager)必须具有您(您的调用者)要求的权限。
这就是覆盖与否之间的区别。如果您不覆盖该方法,那么只有可能拥有特权的调用者的代码位于堆栈上,并且将获得所请求的权限。如果您覆盖该方法,则您的代码也在堆栈上,并且必须具有相应权限。
因此,如果您想实现一个调用继承的check方法的自定义SecurityManager,您必须配置继承的(基于策略的)逻辑以使您的SecurityManager能够授予所有权限。建议将SecurityManager与应用程序的其他部分分开放在不同的代码库中,以便只有SecurityManager而没有其他内容获得充足的权限。

所以他基本上需要涵盖安全管理器的所有可能请求。但是你的回答听起来更专业!+1 - mike
然而,从Oracle文档中建议在public void checkRead(String file)中调用(例如)super.checkRead()。但我一直得到相同的异常抛出。 - Flavio
正如Holger所说,堆栈上的所有内容都会被检查权限。因此,您还需要在子类中实现它们。 - mike
无论您覆盖哪个检查方法,都没有关系。所有这些方法最终都会委托给 checkPermission(Permission) 。它们仅出于历史原因而存在。您可以使用单个 checkPermission 方法控制整个安全管理。但是,如果您覆盖其中任何一个方法并调用其超级实现,则您的代码会在堆栈上,您自定义的安全管理器的代码库必须具有相应的权限,才能使此检查成功。 - Holger
只是为了回忆一下:如果您没有为默认安全管理器配置策略,那么默认情况下几乎不会向JVM之外的任何代码授予权限。您可能获得的唯一权限是“exitVM”,如果您的代码是主应用程序,并且对属于您自己代码库的资源进行文件访问。 - Holger

0

如果您调用超类的checkPermission(p),则无需首先覆盖该类。将其注释掉,然后它就可以工作了。

超类调用java.security.AccessController.checkPermission(perm),当不由java.lang.SecurityManager调用时,似乎会抛出java.security.AccessControlException

在我的情况下,它说:

Could not load Logmanager "null"
java.security.AccessControlException: access denied (java.util.PropertyPermission java.util.logging.manager read)

等等。

public class SecurityManagerExample
{
  public static void main(String[] args)
  {
    System.setSecurityManager(new SecurityManager()
    {
      @Override
      public void checkPermission(Permission p)
      {
        //super.checkPermission(p);
      }
    });

    new JFrame().setVisible(true);
  }
}

我找到了一份关于如何编写安全管理器的教程。我还建议您阅读由Oracle提供的Java文档和示例。


更新

看一下方法摘要,并覆盖你想禁止的功能。 正如我发现的那样,你还需要明确允许你想要的功能。

这里是一个例子:

public class SecurityManagerExample
{

  public static void main(String[] args)
  {
    System.setSecurityManager(new SecurityManager()
    {
      @Override
      public void checkWrite(String file) {
        // no exception is thrown, i. e. creating files is allowed in general
      }

      @Override
      public void checkDelete(String file)
      {
        if (file.equals("test.xml"))
        {
          throw new SecurityException("Not allowed to delete test.xml!");
        }
      }
    });

    File f = new File("test.xml");
    try
    {
      f.createNewFile();
    }
    catch (IOException e)
    {
    }

    f.delete();

  }
}

输出

Exception in thread "main" java.lang.SecurityException: Not allowed to delete test.xml!
    at main.SecurityManagerExample$1.checkDelete(SecurityManagerExample.java:60)
    at java.io.File.delete(File.java:902)
    at main.SecurityManagerExample.main(SecurityManagerExample.java:74)

谢谢Mike,我已经看过那个教程了,但不幸的是它没有帮助到我:( 无论如何,我已经更新了我的代码片段,以便清楚地表明我不仅需要在该方法中调用super.checkPermission(p);,而是我的示例只是一个简化。另外,“注释掉”与根本没有运行SecurityManager的程序具有相同的效果。 - Flavio
然后请检查我在您问题下发布的另一个链接。还有Java文档,以及Oracle上的另一个教程http://docs.oracle.com/javase/tutorial/essential/environment/security.html - mike
自从您更新了您的评论:我的意思是,如果您想要使用基类的功能,请不要扩展它。如果您想要扩展它,请编写自己的策略以确定允许什么或不允许什么。如果您只想禁止特殊情况,则需要覆盖另一个方法。由于所有方法最终都调用`checkPermission',因此很难适当地覆盖它。 - mike

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接