Java安全管理器-SecurityManager

定义:

SecurityManager是Java中的一个类,用于实现安全管理功能。它允许应用程序在运行时对安全策略进行动态管理,并控制哪些操作可以执行,哪些应该被拒绝。主要功能包括:

  • 安全策略管理:SecurityManager允许定义一组安全策略,这些策略规定了在运行时哪些操作是允许的,哪些是禁止的。

  • 权限控制:通过SecurityManager可以控制对敏感资源的访问权限,比如文件系统、网络等。

  • 安全检查:在应用程序执行敏感操作之前,SecurityManager可以进行安全检查,以确保当前线程是否有权限执行该操作。

  • 自定义安全策略:开发人员可以扩展SecurityManager类,实现自定义的安全策略,以满足特定应用程序的安全需求。

尽管SecurityManager提供了强大的安全管理功能,但在现代Java应用程序中,它已经不太常用了。相反,通常会使用更先进的安全解决方案,如安全框架、安全协议等来提供更全面和灵活的安全保护。

沙箱

其实在了解这个SecurityManager 的同时,应该了解一下代码沙箱(sandbox)。是一种安全机制,用于在受信任的环境中执行不受信任的代码,以防止恶意行为或不良影响。它通常用于网络浏览器、虚拟机、容器等环境中,以限制代码的访问权限和影响范围。

在网络浏览器中,代码沙箱允许网页上的 JavaScript 代码在受控制的环境中运行,以防止恶意代码对用户数据或系统的损害。通过沙箱,浏览器可以限制 JavaScript 代码对浏览器 API 和用户系统的访问权限,从而保护用户隐私和系统安全。

在虚拟机和容器中,代码沙箱用于隔离不同的应用程序或服务,以防止其中一个应用程序对其他应用程序或主机系统造成损害。通过沙箱,每个应用程序或服务都被限制在自己的受控环境中运行,不能访问或影响其他应用程序或主机系统。

如何保护代码沙箱呢?

这里就需要我们的安全管理器了SecurityManager,定义了很多权限。我们可以自定义一个类来继承SecurityManager这个类。如下图:

我们这里定义了一个DefaultSecurityManager 类。默认的安全管理器。继承SecurityManager,实现checkPermission方法来进行拦截权限的校验。

当然我们可以使用我们自定义类来编写各种权限的接口哈。

比如:我们创建一个MySecurityManager 类。继承SecurityManager方法。我们可以看看里面都可以实现什么样子的方法。有点像MyBatisPlus。里面已经给你封好方法

这里我实现了几个常用的方法

java 复制代码
/**
 * 我的安全管理器
 */
public class MySecurityManager extends SecurityManager {

    @Override
    public void checkPermission(Permission perm) {
        //默认情况下,不做任何检查  所有权限放开
//        super.checkPermission(perm);
    }

    /**
     * 检查执行系统命令的权限。
     *
     * @param cmd the specified system command.
     */
    @Override
    public void checkExec(String cmd) {
        throw new SecurityException("checkExec 权限异常:" + cmd);
    }

    /**
     * 检查读取文件的权限。是否允许读文件
     *
     * @param file the system-dependent filename.
     */
    @Override
    public void checkRead(String file) {
        if (file.contains("F:\\Code\\CaDaOJ-code-sandbox\\")) {
            return;//放行
        }
        throw new SecurityException("checkRead权限异常:" + file);
    }

    /**
     * 检查写文件的权限。
     *
     * @param file the system-dependent filename.
     */
    @Override
    public void checkWrite(String file) {
        throw new SecurityException("checkWrite 权限异常:" + file);
    }

    /**
     * 检查删除文件的权限。
     *
     * @param file the system-dependent filename.
     */
    @Override
    public void checkDelete(String file) {
        throw new SecurityException("checkDelete 权限异常:" + file);

    }

    /**
     * 检查程序是否可以连接网络
     *
     * @param host the host name port to connect to.
     * @param port the protocol port to connect to.
     */
    @Override
    public void checkConnect(String host, int port) {
        throw new SecurityException("checkConnect权限异常:" + host + ":" + port);
    }
}

启动

在我们需要校验的地方直接加上这句话

java 复制代码
System.setSecurityManager(new DefaultSecurityManager())

实际运用

实际情况下,不应该在主类中做限制,只需要限制子程序的权限即可。

启动子进程执行命令时,设置安全管理器,而不是在外层设置。

当然也可以把他整成一个配置文件。把它放到 resources/security目录下,配置类编写成一个Java源文件,然后使用Java编译器将其编译成字节码文件(.class),最后将这个字节码文件作为资源打包到你的应用程序中。
注意:移除类的包名!移除类的包名!移除类的包名!

创建一个Java源文件,命名为MySecurityManager.java,包含你的配置类代码:

java 复制代码
import java.security.Permission;

public class MySecurityManager extends SecurityManager {

    @Override
    public void checkPermission(Permission perm) {
        // 在这里实现你的权限检查逻辑
        // 这只是一个简单的示例,可以根据具体情况进行修改
        if (perm.getName().equals("setSecurityManager")) {
            // 如果试图设置SecurityManager,则抛出SecurityException
            throw new SecurityException("权限不足");
        }
    }

    // 其他重写的checkXXX方法根据需要进行实现
    // 例如:checkRead、checkWrite等等
}

使用Java编译器(javac)编译MySecurityManager.java文件,生成字节码文件MySecurityManager.class:
javac MySecurityManager.java

在你的应用程序中,使用ClassLoader加载嵌入的MySecurityManager类:

java 复制代码
import java.io.InputStream;

public class Main{

    public static void main(String[] args) {
        // 使用ClassLoader加载嵌入的资源文件
        ClassLoader classLoader = MyApp.class.getClassLoader();
        try (InputStream inputStream = classLoader.getResourceAsStream("MySecurityManager.class")) {
            byte[] buffer = new byte[inputStream.available()];
            inputStream.read(buffer);
            // 使用defineClass方法加载类
            Class<?> mySecurityManagerClass = ClassLoader.defineClass("MySecurityManager", buffer, 0, buffer.length);
            // 创建并设置自定义的SecurityManager
            SecurityManager sm = (SecurityManager) mySecurityManagerClass.getDeclaredConstructor().newInstance();
            System.setSecurityManager(sm);

            // 程序的其他逻辑...
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

这样,你就可以将配置类作为资源嵌入到你的应用程序中,并在运行时使用ClassLoader加载它,从而设置自定义的SecurityManager。请注意,这种方法可能会增加应用程序的复杂性,建议在需要时使用。

相关推荐
Scott9999HH8 小时前
【IIoT流量实战】蒸汽管道阀门全关却仍有流量?用 Python 实现涡街信号 FFT 频谱分析与温压全补偿积算网关,深度拆解靠谱的涡街流量计厂家硬核技术标准
开发语言·python
腻害兔8 小时前
【若依项目-产品经理视角】深度拆解 RuoYi-Vue-Pro 商城模块:从商品管理到交易引擎,50 张表撑起一整套电商系统
java·大数据·vue.js·产品经理·ai编程
码智社9 小时前
AES加密原理详解及Java实现加解密实战
java·开发语言
AI云海9 小时前
python 列表、元组、集合和字典
开发语言·python
萧瑟余晖10 小时前
JDK 26 新特性详解
java·开发语言
马优晨10 小时前
Freemarker 完整讲解(后端 Java 模板引擎)
java·开发语言·freemarker·freemarker 完整讲解·freemarker模板引擎
人邮异步社区12 小时前
怎么把C语言学到精通?
c语言·开发语言
九硕智慧建筑一体化厂家13 小时前
直流智能照明|一站式低碳照明解决方案,安全、节能、降本、全场景适配
安全
心平气和量大福大13 小时前
C#-WPF-控件-TextBox 数据绑定
开发语言·c#·wpf
ttwuai13 小时前
Cursor 生成 CRUD 后,Go 后台接口别只测 200:JWT、RBAC 和 tenant_id 怎么验
开发语言·后端·golang