Java 安全管理器与访问控制器
我试图阻止玩家的某些行为,但不是阻止我的游戏基础设施,为此我使用了一个安全管理器。看起来像这样Java 安全管理器与访问控制器,java,security,Java,Security,我试图阻止玩家的某些行为,但不是阻止我的游戏基础设施,为此我使用了一个安全管理器。看起来像这样 public class GameSecurityManager extends SecurityManager { @Override public void checkPackageAccess(String pkg) { super.checkPackageAccess(pkg); if (isPlayer()) { if (pkg.startsWith("ca.hilikus.jrob
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,而定制安全管理器(通过子类化)应该是最后的选择,并且应该非常小心地完成
你同意这个说法吗?有人能解释这是为什么吗?如果是这样的话,我将如何完成类似于我粘贴的示例代码的工作?我试图阻止反射、线程和基于上下文实例化一些对象(如上面的
isPlayer()
)。访问控制javadoc讨论的唯一一件事是特殊代码块中的特权操作,但它没有显示如何使用控制器来实际阻止操作您不需要编写自己的SecurityManager或AccessController,您需要的是自定义。在您编写一个之后,您只需要启动SecurityManager并对您想要保护的每个方法进行安全检查!您可能需要执行私密操作以避免过多检查传播。:) (为了未来用户的利益)
答案是您应该为应用程序提供一个安全策略。如果这是不可能控制的,那么你就是运气不好
在策略中,您将为“托管扩展”授予对某些合适子集的访问权限,其中“游戏包”将被授予所有权限。然后,为库创建权限,并授予对“托管扩展”的适当访问权
然后在您的API中,您将执行以下操作:
公共字符串someMethod(字符串someArg)
{
if(System.getSecurityManager()==null)
返回internalSomeMethod(someArg);
MyPermission required=新的MyPermission(“任何”);
AccessController.checkPermission(必需);
return AccessController.doPrivileged(新的PrivilegedAction()
{
公共字符串run()
{
返回内部方法(somArg);
}
} );
}
私有字符串someInternalMethod(字符串someArg){…}
因此,即使“托管扩展”只有“MyPermission”,游戏引擎也可以拥有所有权限并允许做任何它想做的事情,而“扩展”甚至不能读取系统属性。引用本书“6.4.9SecurityManager
与AccessController
”一节:
回想一下本章前面的调用安全检查时,调用checkPermission
和调用SecurityManager
类中定义的其他check
方法之间的区别。然后,选择取决于您是否依赖于任何Java 2之前的安全管理器类。现在您有了另一个选择:调用SecurityManager
中定义的checkPermission
方法或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提供的安全管理器,并且未参考AccessController
或其等效工具,则可能不会考虑特权状态
您可能想知道我们为什么提供这些选择。一种做事的方式还不够好吗?这些选择基于经验。需要在通用性和一致性之间进行平衡。从长远来看,我们希望不经常需要定制安全管理器,而且即使定义了它们,它们也将基于AccessController
中的现有功能构建。特别是,它们将提供额外的功能,而不是促进不兼容的行为。然而,在一个必须强制执行截然不同的安全策略的特殊环境中,定制的安全管理器可能无法实现
AccessController.checkPermission(permission);