Groovy安全高效的执行(死循环,休眠,危险方法)

news2024/11/25 16:27:31

背景

在很多场景下有需要执行异步任务,或者执行用户的自定义任务时,通常我们会使用Groovy脚本能力来完成任务。通过groovy动态脚本能力,在业务执行过程中动态执行不同业务线或者用户的脚本,来满足不同需求。
这样可以非常方便的进行业务拓展,但是也会带来一系列安全问题,
1 比如在脚本中调用了系统危险的方法,如System.exit 会导致整个服务停止
2 触发了死循环等场景,会导致任务卡死,使用多线程的话线程也很块就被占完。
3 使用Thread.sleep 将线程进行休眠

解决方案

关于以上三类问题,这里也进行了归纳总结,给出对应的方案

死循环执行

1 先定义一个死循环执行脚本,功能就是一直打印就可以了

    private static String script = "import groovy.transform.TimedInterrupt\n" +
            "\n" +
            "import java.util.concurrent.TimeUnit\n" +
            "\n" +
            "class GroovyScriptTest {\n" +
            "    public String execute(String key) {\n" +
            "        while (true) {\n" +
            "            print(11);\n" +
            "        }\n" +
            "        return key + \":updated\";\n" +
            "    }\n" +
            "}\n";

为了方便查看生成后的源码,这里将生成的目录设置为target目录下

  public class GroovyClassLoaderTest2 {
    private static String script = "import groovy.transform.TimedInterrupt\n" +
            "\n" +
            "import java.util.concurrent.TimeUnit\n" +
            "\n" +
            "class GroovyScriptTest {\n" +
            "\n" +
            "    public String execute(String key) {\n" +
            "        while (true) {\n" +
            "            print(11);\n" +
            "        }\n" +
            "        return key + \":updated\";\n" +
            "    }\n" +
            "}\n";

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {

        CompilerConfiguration config = new CompilerConfiguration();
        config.setTargetDirectory(GroovyClassLoaderTest2.class.getClassLoader().getResource("./").getPath());

        // 重置调用时间
        GroovyClassLoader groovyClassLoader = new GroovyClassLoader(GroovyClassLoaderTest2.class.getClassLoader(), config);
        Class aClass = groovyClassLoader.parseClass(script);
        GroovyObject groovyObject = (GroovyObject) aClass.newInstance();
        Object o = groovyObject.invokeMethod("execute", "key");
        System.out.println("groovy执行结果:" + o);

    }

}

可以看到 运行起来后控制台一直在输出1,在实际业务场景中,我们需要对这种行为进行管控,可以使用Groovy自带的注解

@TimedInterrupt(unit = TimeUnit.MILLISECONDS, value = 1000L)

这里可以对方法进行执行时间设置,可以指定执行时间单位和时间,比如这里设置执行为1000ms,到时间后任务将自动结束
在这里插入图片描述
这样就达到了我们需要的效果。

Thread.sleep问题

在脚本中使用了指定睡眠时间的场景,如适用Thread.sleep(100000)会严重的拖慢了整体执行效率,此时可以通过Groovy自带的机制

@groovy.transform.ThreadInterrupt

添加此注解后,我们可以主动设置线程为已中断的,如果使用线程池的话可以使用futuretask的cancel(true)方式超时中断线程

危险方法调用

这里有两种方式,一种是通过执行过程中的拦截器进行处理,可以查看GroovyInterceptor,还有就是在编译期间就识别出来危险方法,在前置阶段进行拦截(SecureASTCustomizer.ExpressionChecker),核心代码如下:

public static class NoSupportClassTest implements SecureASTCustomizer.ExpressionChecker {
        @Override
        public boolean isAuthorized(Expression expression) {
            if (expression instanceof MethodCallExpression) {
                MethodCallExpression mc = (MethodCallExpression) expression;
                String className = mc.getReceiver().getText();
                String method = mc.getMethodAsString();

                System.out.println("=====>"+className + "." + method);

            }
            return true;
        }
    }

只要识别到需要拦截的方法,这里返回false就可以进行前置拦截。

原理分析

通过以上两种方式,可以对循环(for,while)和线程睡眠的方式进行拦截处理,到target目录下查看生成的class文件,在方法执行的时候会先判断线程是否已经被中断了,在每个循环执行的时候会判断下执行时间,这样组合起来就可以非常好的达到了我们需要的业务效果。在这里插入图片描述

完整代码

public class GroovyClassLoaderTest3 {
    private static String script = "import groovy.transform.TimedInterrupt\n" +
            "\n" +
            "import java.util.concurrent.TimeUnit\n" +
            "\n" +
            "class GroovyScriptTest {\n" +
            "\n" +
            "    @TimedInterrupt(unit = TimeUnit.MILLISECONDS, value = 1000L)\n" +
            "    @groovy.transform.ThreadInterrupt\n" +
            "    public String execute(String key) {\n" +
            "        while (true) {\n" +
            "            print(11);\n" +
            "        }\n" +
            "        return key + \":updated\";\n" +
            "    }\n" +
            "}\n";

    public static void main(String[] args) throws InstantiationException, IllegalAccessException {
        CompilerConfiguration config = new CompilerConfiguration();
        config.setTargetDirectory(GroovyClassLoaderTest3.class.getClassLoader().getResource("./").getPath());

        SecureASTCustomizer secure = new SecureASTCustomizer();
        secure.addExpressionCheckers(new NoSupportClassTest());
        config.addCompilationCustomizers(secure);

        // 重置调用时间
        GroovyClassLoader groovyClassLoader = new GroovyClassLoader(GroovyClassLoaderTest3.class.getClassLoader(), config);
        Class aClass = groovyClassLoader.parseClass(script);
        GroovyObject groovyObject = (GroovyObject) aClass.newInstance();
        Object o = groovyObject.invokeMethod("execute", "key");
        System.out.println("groovy执行结果:" + o);

    }

    public static class NoSupportClassTest implements SecureASTCustomizer.ExpressionChecker {
        @Override
        public boolean isAuthorized(Expression expression) {
            System.out.println(expression);
            if (expression instanceof MethodCallExpression) {
                MethodCallExpression mc = (MethodCallExpression) expression;
                String className = mc.getReceiver().getText();
                String method = mc.getMethodAsString();

                System.out.println("=====>"+className + "." + method);

            }
            return true;
        }
    }

}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/116187.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

关于CSS选择器优先级的规则说明

简单规则&#xff1a; !important > 行内样式 > id选择器 > 类选择器 > 元素选择器 > 通配选择器 选择器举例说明&#xff1a; !important&#xff1a; <h1 id"title">好好学习&#xff0c;天天向上</h1> <style type"text/…

ArcGIS基础实验操作100例--实验1绘制自定义线、垂线、平行线

本实验专栏来自于汤国安教授《地理信息系统基础实验操作100例》一书 实验平台&#xff1a;ArcGIS 10.6 实验数据&#xff1a; 通过百度网盘分享的文件&#xff1a;地理信息系统基础实验100例 链接:https://pan.baidu.com/s/1sprJ2eyDAkYWiLwyuTIf1g 提取码:gb7y 复制这段内容…

Doris(一)

1、Doris简介 Doris是由百度大数据研发&#xff0c;是一个现代化的MPP&#xff08;Massively Parallel Processing&#xff09;大规模并行处理的分析型数据库产品。仅需亚秒级响应时间即可获得查询结果&#xff0c;有效地支持实时数据分析。 Apache Doris 的分布式架构非常简洁…

北上广深杭房价高压下,这也许是软件测试员扎根的唯一出路...

简单算一笔账&#xff0c;目前小公司软件测试员工资一般是1万出头&#xff0c;年薪普遍在20万以下。在不考虑通胀和工资增长的情况下&#xff0c;除去吃喝需要攒30年才能攒出一线城市房子的首付&#xff0c;以这样的收入水平&#xff0c;基本上没法扎根。 想拿高薪最好的途径就…

API文档、技术文档工具 - ShowDoc - 使用

1.应用场景 主要用于使用适合IT团队的 API文档、技术文档工具 进行项目文档书写以及进行开发。 2.学习/操作 1.文档阅读 ShowDoc ShowDoc - demo 安装/升级手册 GitHub - star7th/showdoc: ShowDoc is a tool greatly applicable for an IT team to share documents online一…

LeetCode Hot 100~Day3

目录 字母异位词分组 最大子数组和 跳跃游戏 合并区间 不同路径 最小路径和 爬楼梯 颜色分类 子集 单词搜索 二叉树的中序遍历 不同的二叉搜索树 字母异位词分组 题目链接&#xff1a;49. 字母异位词分组 示例 输入: strs ["eat", "tea&quo…

[DonkeyCar][树莓派]基础01 - 首次配置 - WIFI

2022年圣诞节到来啦&#xff0c;疫情把刚刚起来的工作似乎又慢了下来&#xff0c;在冲刺决赛圈的同时&#xff0c;也许开一个新的领域&#xff0c;写一个博客是比较好的方式。 一、前言 拿到树莓派开发板的时候&#xff0c;一般&#xff0c;供应商都会配合烧录的镜像。但是&am…

《图解TCP/IP》阅读笔记(第七章 7.6)—— BGP 边界网关协议

7.6 BGP BGP&#xff08;Border Gateway Protocol&#xff09;&#xff0c;边界网关协议&#xff0c;是用于连接不同组织机构&#xff08;或者说不同自治系统&#xff09;的一种协议&#xff0c;其属于EGP&#xff08;外部网关协议&#xff09;&#xff0c;我们在7.2节中了解过…

01)FastDFS文件服务器安装和测试可用性

FastDFS简介 ​ FastDFS是一个轻量级的开源分布式文件系统。2008年4月份开始启动。类似google FS的一个轻量级分布式文件系统,纯C实现,支持Linux、FreeBSD、AIX等UNIX系统。 ​ 主要解决了大容量的文件存储和高并发访问的问题,文件存取时实现了负载均衡。实现了软件方式的…

PicoRV32 笔记 06 压缩指令集

PicoRV32 中实现压缩指令集选项 COMPRESSED_ISA&#xff0c;当设置COMPRESSED_ISA1开启支持16位指令集。压缩指令有很多优点&#xff0c;当我们在FPGA中实现PicoRV32的时候&#xff0c;使用RISCV的C扩展能有效的增大代码密度&#xff0c;原本32位1条指令变为16位一条指令&#…

synchronized 和 ReentrantLock 的区别

&#x1f388;专栏链接:多线程相关知识详解 synchronized和ReentrantLock的 区别 缺点 优势 synchronized和ReentrantLock两者都是可重入锁 ReentrantLock的三个核心方法: Ⅰ.lock(加锁) Ⅱ.unlock(解锁) Ⅲ.tryLock(尝试加锁) import java.util.concurrent.locks.Reentrant…

Android并发编程里的线程原理

1.进程和线程的概念 抛开那些官方的概念&#xff0c;我们可以大致理解为:进程就是手机里运行的一个个应用&#xff0c;他们都是一个个的进程&#xff08;当然&#xff0c;有些App是多进程的&#xff0c;这个先不谈&#xff09;。线程则是进程中对应的一个任务的执行控制流。如果…

广播机制-案例

广播机制-案例 1.静态注册案例-接收开机广播 1.案例&#xff1a;接收开机的广播 创建自定义的BroadcastReceiver用于处理监听到的系统广播。//接收系统开机的广播事件 public class BootCompleteReceiver extends BroadcastReceiver {Overridepublic void onReceive(Context co…

2023跨境出海指南:马来西亚网红营销白皮书

当前的东南亚市场可谓是是企业出海的大热门&#xff0c;马来西亚作为东南亚地区的第三大经济体&#xff0c;其发展形势也是一片大好。疫情出现后&#xff0c;马来西亚的娱乐和消费转移到线上&#xff0c;对社媒的依赖也催发了网红经济的发展。本文Nox聚星就和大家探讨一下&…

海康威视人脸识别设备对接(一)环境搭建

需要对接海康威视人脸识别设备&#xff0c;这里选择明眸门禁&#xff0c;还有其他的没研究过 打开海康威视开放平台 https://open.hikvision.com/ 选择开放体系&#xff0c;一直选择到设备集成SDK 这里我选择设备网络SDK 点击查看详情 选择对应的版本&#xff0c;我用笔记…

AD入门学习—原理图的绘制3

目录 2.4 CAN&24C02及DS18B20温度传感单元的绘制 2.5 USB单元的绘制 2.6 SD卡及TFT单元的绘制 2.7 NRF24L01单元的绘制 2.8 COM口及PS/2接口的绘制 2.9 DCDC电源输入单元的绘制 2.10 原理图的统一编号及编译检查 学习目录 2.4 CAN&24C02及DS18B20温度传感单元的绘制…

Vue基本指令

1、前端技术的发展&#xff08;html、CSS、JavaScript&#xff09; ​ &#xff08;1&#xff09;jQuery&#xff1a;是对JavaScript进行了封装&#xff0c;使得操作DOM、事件处理、动画处理、ajax交互变得非常简洁、方便。是JavaScript的 库。 ​ &#xff08;2&#xff09…

Moonbeam与Wormhole的Relayer Engine之间的跨链互连合约

如果您不了解Moonbeam&#xff0c;用一句话简单概括来说Moonbeam是跨链通信的中心枢纽。像Axelar、LayerZero和Hyperlane等的协议允许不同EVM上的智能合约互相通信&#xff0c;为Web3 dApp解锁功能方面前所未见的规模。但就目前来说&#xff0c;上述的几个协议的智能合约通信仅…

计算机网络——数据报与虚电路

简介 本篇接上一篇数据交换的内容继续 分组交换其实包含数据报交换和虚电路交换 数据报方式&#xff1a;为网咯层提供外连接服务 虚电报&#xff1a;为网络层提供连接服务 无连接服务&#xff1a;不事先为分组传输确定传输的路径&#xff0c;每个分组独立确定传输路径&#x…

如何实现带动画的动态面包屑,来看看?

大家好&#xff0c;我是派大星&#xff0c;最近在自己手动搭建一个后台管理平台&#xff0c;将其命名为 “雷达行动 Radar-Solution” &#xff0c;在开发的过程中对比了一下其他已经成型的后台解决方案&#xff0c;发现都存在一个共性&#xff0c;就是在Layout的头部都有一个面…