安全管理器与Access Controller

时间:2012-11-25 20:12:43

标签: java security

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

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的情况更糟。但是,我确实找到了this, section 6.2所在的位置

  

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

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

3 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分: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并允许它做任何想做的事情,而“扩展”甚至无法读取系统属性。

答案 2 :(得分:1)

Inside Java 2 Platform Security的“ 6.4.9 SecurityManagerAccessController”一栏中的引用:

  

在本章前面提到,在调用安全性检查时,调用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和Java提供的安全管理器,则可能不会考虑特权状态。不咨询AccessController或其等效内容。

     

您可能想知道我们为什么提供这些选择。做事不够好吗?这些选择基于经验。需要在一般性和一致性之间进行权衡取舍。从长远来看,我们希望不再需要自定义安全管理器,即使定义了安全管理器,它们也将基于AccessController中的现有功能构建。特别是,它们将提供其他功能,而不是促进不兼容的行为。但是,在必须执行极为不同的安全策略的特殊环境中,可以想像的是,定制的安全管理器可能无法使用AccessController实现的算法。

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