18

有没有办法完全禁用 Java 安全管理器?

我正在试验 db4o 的源代码。它使用反射来持久化对象,并且似乎安全管理器不允许反射读取和写入私有或受保护的字段。

我的代码:

public static void main(String[] args) throws IOException {
    System.out.println("start");
    new File( DB_FILE_NAME ).delete();
    ObjectContainer container = Db4o.openFile( DB_FILE_NAME );
    String ob = new String( "test" );
    container.store( ob );
    ObjectSet result = container.queryByExample( String.class );
    System.out.println( "retrieved (" + result.size() + "):" );
    while( result.hasNext() ) {
        System.out.println( result.next() );
    }
    container.close();
    System.out.println("finish");
}

输出:

开始
[db4o 7.4.68.12069 2009-04-18 00:21:30]
 AccessibleObject#setAccessible() 不可用。不能存储私有字段。
检索到 (0):
结束


该线程建议修改 java.policy 文件以允许反射,但它似乎对我不起作用。

我正在使用参数启动 JVM,
-Djava.security.manager -Djava.security.policy==/home/pablo/.java.policy
因此指定的策略文件将是唯一使用的策略文件

该文件如下所示:

授予 {
    权限 java.security.AllPermission;
    权限 java.lang.reflect.ReflectPermission "suppressAccessChecks";
};

我花了最后 3 个小时在这上面,但不知道如何使它工作。任何帮助表示赞赏。

4

3 回答 3

7

您可以尝试将其添加到程序的 main() 中:

System.setSecurityManager(null);

当我遇到安全管理器问题时,为我工作了一个“受信任的”WebStart 应用程序。不确定它是否适用于您的 db4o 案例,但可能值得一试。

编辑:我并不是说这是安全管理器问题的一般解决方案。我只是提出它作为帮助调试原始海报问题的一种方式。显然,如果您想从安全管理器中受益,那么您不应该禁用它。

于 2009-04-18T00:18:29.940 回答
5

您的java.security.policy命令行选项中真的有两个“=”符号吗?那是行不通的。确保您将属性设置为

-Djava.security.policy=/home/pablo/.java.policy

要真正禁用SecurityManager,只需完全放弃java.security.manager系统属性就足够了。


更新:当我阅读策略文件的文档以了解有关“==”语法的更多信息时,我注意到除非策略文件位于当前工作目录中,否则需要将其指定为 URL(包括方案)。您是否尝试过使用“file:”方案为策略路径添加前缀?

我也很困惑,因为(假设您以用户“pablo”的身份运行),看起来该策略应该默认从您的主目录加载,所以您根本不需要指定它。另一方面,如果您不是以用户“pablo”运行,则该文件可能不可读。

于 2009-04-17T22:54:57.440 回答
4

我找到了这个示例,说明如何使您的代码可以访问私有字段和方法。基本上,它归结为Field.setAccessible(true)Method.setAccessible(true)的使用

字段示例:

Field privateStringField = PrivateObject.class.
            getDeclaredField("privateString");

privateStringField.setAccessible(true);

方法示例:

Method privateStringMethod = PrivateObject.class.
        getDeclaredMethod("getPrivateString", null);

privateStringMethod.setAccessible(true);

您还可以考虑将 Groovy 与您的 Java 代码一起使用,因为它(当前)规避了 Java 代码的许多访问级别限制。虽然,此留言板张贴似乎暗示此“功能”可能会在 Groovy 的未来版本中发生变化

于 2009-04-18T05:55:01.597 回答