【Java问题集】Caused by: java.security.AccessControlException: access denied

文章介绍了当遇到`java.security.AccessControlException`异常时,如何查找`java.home`和`user.home`属性,以及如何在`java.policy`文件中添加安全访问策略来解决问题。主要步骤包括检查JRE路径,修改默认的安全策略文件,添加AllPermission配置以允许特定权限。

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录

  • 前言
  • 为什么发生`java.security.AccessControlException`
  • 查找jre系统属性`java.home`和`user.home`
  • 添加安全访问策略


前言

今天在配置Java的测试环境时遇到了下面的错误。

Caused by: java.security.AccessControlException: access denied ("java.io.SerializablePermission" "enableSubclassImplementation")
	at java.security.AccessControlContext.checkPermission(Unknown Source)
	at java.security.AccessController.checkPermission(Unknown Source)
	at java.lang.SecurityManager.checkPermission(Unknown Source)
	at com.sun.javaws.security.JavaWebStartSecurity.checkPermission(Unknown Source)
	一下部分省略

通过查看网络中的文章和JavaDoc文档,总结了解决方法。

为什么发生java.security.AccessControlException

为了防止恶意程序,Java也实现了自己的访问控制机制。通过编写安全策略文件实现访问控制。
默认的安全策略文件的路径为:

  1. ${java.home}/lib/security/java.policy
  2. ${user.home}/.java.policy

因此,首先需要查找jre系统属性java.homeuser.home的值。

查找jre系统属性java.homeuser.home

使用下面的程序,查看jre的路径:

package cn.com.chengq.example;

public class ShowProperties {
    public static void main(String[] args) {
        System.getProperties().forEach((k,v) -> {
            LogUtil.log("%s: %s", k, v);
        });
    }
}

在输出的结果中查找属性java.homeuser.home的值。

添加安全访问策略

在文件${java.home}/lib/security/java.policy${user.home}/.java.policy中添加相应的安全策略配置。
例如上面示例中出现的问题,需要在默认的${java.home}/lib/security/java.policy文件的最后添加配置:


// Standard extensions get all permissions by default

grant codeBase "file:${{java.ext.dirs}}/*" {
        permission java.security.AllPermission;
};

// default permissions granted to all domains

grant {
        // Allows any thread to stop itself using the java.lang.Thread.stop()
        // method that takes no argument.
        // Note that this permission is granted by default only to remain
        // backwards compatible.
        // It is strongly recommended that you either remove this permission
        // from this policy file or further restrict it to code sources
        // that you specify, because Thread.stop() is potentially unsafe.
        // See the API specification of java.lang.Thread.stop() for more
        // information.
        permission java.lang.RuntimePermission "stopThread";

        // allows anyone to listen on dynamic ports
        permission java.net.SocketPermission "localhost:0", "listen";

        // "standard" properies that can be read by anyone

        permission java.util.PropertyPermission "java.version", "read";
        permission java.util.PropertyPermission "java.vendor", "read";
        permission java.util.PropertyPermission "java.vendor.url", "read";
        permission java.util.PropertyPermission "java.class.version", "read";
        permission java.util.PropertyPermission "os.name", "read";
        permission java.util.PropertyPermission "os.version", "read";
        permission java.util.PropertyPermission "os.arch", "read";
        permission java.util.PropertyPermission "file.separator", "read";
        permission java.util.PropertyPermission "path.separator", "read";
        permission java.util.PropertyPermission "line.separator", "read";

        permission java.util.PropertyPermission "java.specification.version", "read";
        permission java.util.PropertyPermission "java.specification.vendor", "read";
        permission java.util.PropertyPermission "java.specification.name", "read";

        permission java.util.PropertyPermission "java.vm.specification.version", "read";
        permission java.util.PropertyPermission "java.vm.specification.vendor", "read";
        permission java.util.PropertyPermission "java.vm.specification.name", "read";
        permission java.util.PropertyPermission "java.vm.version", "read";
        permission java.util.PropertyPermission "java.vm.vendor", "read";
        permission java.util.PropertyPermission "java.vm.name", "read";
   
        permission java.io.SerializablePermission "enableSubclassImplementation";
};

注意策略文件的格式,末尾需要添加分号


本文仅供参考,如有帮助不胜荣幸,请关注、点赞、收藏。
如需转载请注明出处。

你遇到的这个异常: ``` Caused by: java.security.AccessControlException: access denied ("java.io.FilePermission" "file.txt" "read") ``` 是一个典型的 **Java 安全异常(Security Exception)**,表示程序试图执行某个操作(如读取文件),但由于当前 **安全管理器(SecurityManager)** 的限制,**权限不足**导致操作被拒绝。 --- ## 一、异常分析 ### 异常结构: ``` Caused by: java.security.AccessControlException: access denied ("java.io.FilePermission" "file.txt" "read") ``` - `AccessControlException`:表示权限不足,被安全管理器拒绝。 - `"java.io.FilePermission"`:表示这是与文件访问相关的权限。 - `"file.txt"`:表示你试图访问的文件。 - `"read"`:表示你试图执行的操作是“读取”。 --- ## 二、为什么会抛出这个异常? ### 1. **启用了 `SecurityManager`** 你当前的 Java 环境中设置了安全管理器: ```java System.setSecurityManager(new SecurityManager()); ``` 这意味着 Java 开始执行安全策略,限制某些操作。 ### 2. **没有授予文件读取权限** Java 默认的安全策略不允许程序访问本地文件系统资源,除非在策略文件中显式授权。 --- ## 三、示例代码 下面是一个典型的抛出 `AccessControlException` 的 Java 示例: ```java import java.io.FileReader; import java.io.IOException; public class FileReadExample { public static void main(String[] args) { // 设置安全管理器 System.setSecurityManager(new SecurityManager()); try { FileReader reader = new FileReader("file.txt"); int ch; while ((ch = reader.read()) != -1) { System.out.print((char) ch); } reader.close(); } catch (IOException | SecurityException e) { e.printStackTrace(); } } } ``` #### 输出结果: ``` java.security.AccessControlException: access denied ("java.io.FilePermission" "file.txt" "read") at java.base/java.security.AccessControlContext.checkPermission(AccessControlContext.java:485) ... ``` --- ## 四、解决方案 ### ✅ 方法一:使用策略文件授权 创建一个策略文件(例如:`my.policy`): ```java grant { permission java.io.FilePermission "file.txt", "read"; }; ``` 然后运行程序时指定该策略文件: ```bash java -Djava.security.manager -Djava.security.policy=my.policy FileReadExample ``` 这样程序就有权限读取 `file.txt` 了。 --- ### ✅ 方法二:完全禁用安全管理器(不推荐) 如果你不需要安全限制,可以不设置安全管理器: ```java // System.setSecurityManager(new SecurityManager()); // 注释掉这一行 ``` 这样就不会触发 `AccessControlException`。 --- ### ✅ 方法三:使用 `AccessController.doPrivileged()`(高级用法) 如果你使用的是自定义类加载器或模块化系统,可以使用特权代码块: ```java import java.security.AccessController; import java.security.PrivilegedAction; import java.io.*; public class PrivilegedFileRead { public static void main(String[] args) { System.setSecurityManager(new SecurityManager()); String content = AccessController.doPrivileged((PrivilegedAction<String>) () -> { StringBuilder sb = new StringBuilder(); try (BufferedReader reader = new BufferedReader(new FileReader("file.txt"))) { String line; while ((line = reader.readLine()) != null) { sb.append(line).append("\n"); } } catch (IOException e) { e.printStackTrace(); } return sb.toString(); }); System.out.println(content); } } ``` > ⚠️ 注意:这种方法需要在策略文件中为代码源授予 `AllPermission` 或特定权限。 --- ## 五、总结 | 项目 | 描述 | |------|------| | 异常类型 | `AccessControlException` | | 抛出原因 | 安全管理器拒绝操作(如读取文件) | | 典型场景 | 使用了 `SecurityManager`,但没有授予相应权限 | | 解决方法 | 使用策略文件授权、禁用安全管理器、使用 `doPrivileged()` | --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值