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。请注意,这种方法可能会增加应用程序的复杂性,建议在需要时使用。

相关推荐
XiaoLeisj2 小时前
【JavaEE初阶 — 多线程】单例模式 & 指令重排序问题
java·开发语言·java-ee
paopaokaka_luck2 小时前
【360】基于springboot的志愿服务管理系统
java·spring boot·后端·spring·毕业设计
dayouziei2 小时前
java的类加载机制的学习
java·学习
励志成为嵌入式工程师3 小时前
c语言简单编程练习9
c语言·开发语言·算法·vim
捕鲸叉3 小时前
创建线程时传递参数给线程
开发语言·c++·算法
A charmer3 小时前
【C++】vector 类深度解析:探索动态数组的奥秘
开发语言·c++·算法
Peter_chq3 小时前
【操作系统】基于环形队列的生产消费模型
linux·c语言·开发语言·c++·后端
Yaml44 小时前
Spring Boot 与 Vue 共筑二手书籍交易卓越平台
java·spring boot·后端·mysql·spring·vue·二手书籍
小小小妮子~4 小时前
Spring Boot详解:从入门到精通
java·spring boot·后端
hong1616884 小时前
Spring Boot中实现多数据源连接和切换的方案
java·spring boot·后端