我试图阻止玩家的某些操作,但不是来自我的游戏基础架构,因为我正在使用安全管理器。看起来像这样
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唯一讨论的是特殊代码块中的特权操作,但它没有显示如何使用控制器来实际阻止操作
答案 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 SecurityManager
与AccessController
”一栏中的引用:
在本章前面提到,在调用安全性检查时,调用
checkPermission
和调用check
类中定义的其他SecurityManager
方法之间的区别。然后,选择取决于您是否依赖任何Java 2之前的安全管理器类。现在您有另一种选择:调用checkPermission
中定义的SecurityManager
方法或AccessController
中定义的方法。这些方法在两种主要方式上有所不同。首先,有时不存在已安装的
SecurityManager
,因此您无法在其上调用check
或checkPermission
方法。相反,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部分。