如何禁用 Java 安全管理器?

Posted

技术标签:

【中文标题】如何禁用 Java 安全管理器?【英文标题】:How to disable Java security manager? 【发布时间】:2010-10-20 05:35:49 【问题描述】:

有没有办法完全禁用 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): 结束

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

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

文件如下所示:

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

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

【问题讨论】:

您是否尝试过从您自己的代码中调用 setAccessible 或其他特权操作? 完整的命令行也可能有用。 你的虚拟机参数正确吗?你似乎有 -Djava.security.policy== ? @Brian: double '=' 表示指定文件是唯一使用的策略文件。单个“=”表示指定文件将与标准策略文件一起使用。至少那是读过的内容。 @Tom:我可以在我的代码中调用 setAccesible,这很奇怪,因为我的代码是我在 db4o 源代码中添加的一个类。然而,同一个 db4o 似乎无法访问 setAccesible。也许这是 db4o 中的一个错误? 【参考方案1】:

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

System.setSecurityManager(null);

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

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

【讨论】:

一般不建议这样做,因为它可能被恶意代码用来降低安全性并获得本地用户权限。 原发帖人正在希望“完全禁用”安全管理器! :-) 谢谢,我在“受信任的”WebStart 应用程序中遇到异常并调用 System.setSecurityManager(null);为我工作 嗯,安全管理器可以防止设置安全管理器,这对攻击者不利,但它允许创建一个“超级”安全管理器,在整个程序流程的其余部分保持永久不变。 @gparyani:正确,谢谢。详细说明您的观点,该程序必须具有java.lang.RuntimePermissionsetSecurityManager 权限才能设置安全管理器。【参考方案2】:

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

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

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


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

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

【讨论】:

那行不通。两者都不会将任何参数传递给 JVM。 BTW '==' 表示指定的文件将是唯一使用的文件。单个“=”表示该文件将与标准策略文件一起使用。至少这是我读到的。【参考方案3】:

我找到了这个如何make private fields and methods accessible 到您的代码的示例。基本上,它归结为 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);

您还可以考虑在 Java 代码中使用 Groovy,因为它(当前)绕过了 Java 代码的大部分访问级别限制。虽然,这个留言板帖子似乎暗示了这个“功能”may change in future versions of Groovy。

【讨论】:

通过禁用安全管理器,您可以获得调用 setAccessible(true) 的权限。如果不禁用安全管理器,您将无法祈祷。 @Kevin:我可以在自己的代码中为私有字段调用 setAccesible。 “我自己的代码”是指我添加到 db4o 源代码中的一个类。 你应该能够在你的代码上调用它,只要你没有在一个小程序或其他环境中运行它,就像 (+1) @extraneon 建议的那样,它有一个违反安全管理器的环境。这篇文章对 Java 安全管理器有很好的解释:artima.com/underthehood/securitymanager.html

以上是关于如何禁用 Java 安全管理器?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法在 Java 中执行不安全的代码(禁用安全管理器)?

如何禁用自动隐藏解决方案资源管理器(Visual Studio 2017)

可以禁用 Windows 上 Java 的“单点登录”(使用“凭据管理器”中的凭据)吗?

如何启用 HSQLDB 管理器工具菜单,因为它已被禁用

如何禁用适用于 Windows 的 Git 凭据管理器?

如何禁用 s-s-rS 2008 管理器