3

我试图阻止玩家的某些操作,但不是我的游戏基础设施,为此我正在使用安全管理器。看起来像这样

public class GameSecurityManager extends SecurityManager {
@Override
public void checkPackageAccess(String pkg) {
 super.checkPackageAccess(pkg);
 if (isPlayer()) {
  if (pkg.startsWith("ca.hilikus.jrobocom")) {
   if (!"ca.hilikus.jrobocom.player".equals(pkg) && !"ca.hilikus.jrobocom.robot.api".equals(pkg)) {
        throw new SecurityException("No access to game packages");
   }}}
}
}

关于安全管理器的文档非常稀少,大部分来自 90 年代。AccessController 的情况更糟。但是,我确实找到了这一点,第 6.2 节指出

我们鼓励在应用程序代码中使用 AccessController,而自定义安全管理器(通过子类化)应该是最后的手段,并且应该非常小心。

你同意这个说法吗?有人可以解释为什么会这样吗?如果是这种情况,我将如何完成与我粘贴的示例代码类似的事情?我试图阻止诸如反射、线程化和基于上下文实例化一些对象之类的事情(isPlayer()如上所示)。访问控制 javadoc 讨论的唯一内容是特殊代码块中的特权操作,但它没有显示如何使用控制器来实际阻止操作

4

3 回答 3

2

引用Inside Java 2 Platform Security一书的“6.4.9 SecurityManagervs ”部分:AccessController

回想本章前面的区别,当调用安全检查时,调用checkPermission和调用类中定义的其他check方法之间的区别SecurityManager。那时的选择取决于您是否依赖于任何 Java 2 之前的安全管理器类。现在您有另一种选择:调用中checkPermission定义的方法SecurityManager或中定义的方法AccessController。这些方法在两个主要方面有所不同。

首先,有时没有安装SecurityManager存在,所以你不能在它上面调用checkcheckPermission方法。相比之下,中的静态方法AccessController总是可以调用的。回想一下调用的以下成语SecurityManager

SecurityManager sm = System.getSecurityManager();
if (sm != null)
    sm.checkPermission(permission);

但你总是可以打电话

AccessController.checkPermission(permission);

因此,无论是否SecurityManager安装了系统范围,如果您想确保始终调用安全检查,您应该调用AccessController. 但是请注意,一些现有应用程序会测试是否安装了SecurityManager. 然后,根据表示一种或其他安全状态的测试结果,这些应用程序采取不同的操作。对于这些应用程序的向后兼容性,调用SecurityManager更为合适。

第二个区别是调用SecurityManager不保证特定的访问控制算法;有人可能已经扩展它并安装了自定义安全管理器。相比之下,调用AccessController保证使用前面指定的完全访问控制算法。因此,如果您不想将安全检查委托给自定义安全管理器,则应AccessController直接调用。否则,调用SecurityManager.

另外,请注意,由于SecurityManager该类定义了用于安全检查的通用接口,它不提供AccessController已定义的特权机制。事实上,如果您在代码中使用特权机制,但后来调用SecurityManager执行安全检查,如果您安装的安全管理器不是 Java 2 提供的并且不咨询AccessController或其相等的。

您可能想知道为什么我们提供这些选择。一种做事方式还不够好吗?这些选择基于经验。需要在通用性和一致性之间进行平衡权衡。从长远来看,我们预计不会经常需要自定义安全管理器,并且即使定义了它们,它们也将建立在AccessController. 特别是,它们将提供额外的功能,而不是促进不兼容的行为。然而,在一个必须强制执行完全不同类型的安全策略的特殊环境中,可以想象,定制的安全管理器可能无法使用由AccessController.

您还可以查看Oracle 的 Java 平台标准版安全开发人员指南中的SecurityManager 与 AccessController部分。

于 2018-11-10T10:13:58.917 回答
1

您不需要编写自己的 SecurityManager 或自己的 AccessController,您需要的是自定义Permission。在你写完一个之后,你只需要启动一个 SecurityManager 并在你想要保护的每个方法中进行安全检查!您可能需要执行特权操作以避免过多的检查传播。:)

于 2012-11-25T21:25:32.133 回答
1

(为了未来用户的利益)

答案是您应该为应用程序提供安全策略。如果这是无法控制的,那么你就是不走运。

在策略中,您将授予对“托管扩展”的某些合适子集的访问权限,而您的“游戏包”将被授予 AllPermissions。然后,您为您的库创建权限并授予对“托管扩展”的适当访问权限。

然后在您的 API 中,您会执行以下操作;

public String someMethod( String someArg )
{
    if( System.getSecurityManager() == null )
        return internalSomeMethod( someArg );
    MyPermission required = new MyPermission( "whatever" );
    AccessController.checkPermission( required );
    return AccessController.doPrivileged(new PrivilegedAction<String>()
    {
        public String run()
        {
            return internalSomeMethod( somArg );
        }
    } );
}

private String someInternalMethod( String someArg ){...}

因此,即使“托管扩展”只有“MyPermission”,游戏引擎也可以拥有 AllPermissions 并允许做它想做的任何事情,而“扩展”甚至无法读取系统属性。

于 2013-11-14T05:33:46.807 回答