Web安全之GroovyShell讲解:错误与正确示范,安全问题与解决方案

第一章、引言

Groovy 是一门基于 Java 虚拟机(JVM)的动态语言,而 GroovyShell 是 Groovy 提供的一个灵活强大的脚本执行工具。通过 GroovyShell,开发者可以在运行时动态执行 Groovy 脚本,它的灵活性非常适合那些需要动态编译与执行脚本的应用场景。本文详细介绍三种方式解决,包括CompilerConfigurationSecurityManagerScript Sandbox用法和案例。

第二章、GroovyShell 基础介绍

GroovyShell 是 Groovy 核心 API 的一部分,用来在运行时执行动态 Groovy 脚本。与 Java 的静态编译不同,GroovyShell 可以在应用运行时执行传入的字符串形式的代码,非常适合动态配置或运行时脚本计算的场景。

2.1 GroovyShell 主要类

  • GroovyShell:核心执行类,接受字符串形式的脚本并执行。
  • Binding:用于将变量传递到 Groovy 脚本中,使其可以在脚本内访问 Java 对象。
  • Script:表示一段 Groovy 脚本,允许在多次执行中复用脚本内容。

2.2 GroovyShell 的基本用法

使用 GroovyShell 可以非常简单地执行一段 Groovy 脚本。以下是一个基础的示例,演示如何通过 GroovyShell 动态执行一段计算逻辑。

import groovy.lang.GroovyShell;

public class GroovyShellExample {
    public static void main(String[] args) {
        GroovyShell shell = new GroovyShell();
        Object result = shell.evaluate("3 + 5");
        System.out.println("Result: " + result);  // 输出:Result: 8
    }
}

在该示例中,GroovyShell.evaluate() 方法接受一段 Groovy 脚本作为字符串并执行,返回脚本执行的结果。

2.3. 类图与时序图

GroovyShell 类图
在这里插入图片描述

该类图展示了 GroovyShellBindingScript 的关系,GroovyShell 通过 Binding 传递上下文变量,并最终执行 Script

GroovyShell 脚本执行时序图

在这里插入图片描述

该时序图展示了用户通过 GroovyShell 传递脚本和上下文变量,GroovyShell 将这些变量通过 Binding 传递给脚本,最后由 SecureScript 进行安全执行并返回结果的过程。

第三章、电商交易系统中的 GroovyShell 示例

在电商交易系统中,可能会需要动态配置一些业务逻辑,例如根据订单金额、用户类型、折扣策略等计算总价。通过 GroovyShell,开发者可以灵活地将这些业务规则编写成脚本,然后在运行时加载和执行。

3.1 正常场景示范:动态计算订单总价

假设我们需要通过 GroovyShell 动态执行一段业务逻辑来计算订单的总价,这段脚本根据订单金额和用户类型应用不同的折扣。

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

public class OrderPricingService {
    public static void main(String[] args) {
        // 准备脚本的上下文
        Binding binding = new Binding();
        binding.setVariable("orderAmount", 1000);
        binding.setVariable("userType", "VIP");

        // 动态执行的 Groovy 脚本
        String script = "if (userType == 'VIP') { return orderAmount * 0.8 } else { return orderAmount }";

        GroovyShell shell = new GroovyShell(binding);
        Object result = shell.evaluate(script);

        System.out.println("Final price: " + result);  // 输出:Final price: 800.0
    }
}

在这个示例中,orderAmountuserType 是通过 Binding 传递给 Groovy 脚本的变量,脚本根据用户类型判断是否给予折扣。如果用户是 VIP,将给予 20% 的折扣。

3.2 恶意攻击示范:未处理的输入导致脚本注入攻击

如果在电商交易系统中,脚本是由外部用户输入提供的,那么这可能会导致严重的安全漏洞。假设开发者没有对传入的脚本进行任何校验,恶意用户可能会注入危险代码,进而影响系统安全。

import groovy.lang.Binding;
import groovy.lang.GroovyShell;

public class UnsafeGroovyShellExample {
    public static void main(String[] args) {
        // 恶意用户提供的输入脚本
        String maliciousScript = "orderAmount * 0.8; Runtime.getRuntime().exec('rm -rf /');";

        Binding binding = new Binding();
        binding.setVariable("orderAmount", 1000);

        GroovyShell shell = new GroovyShell(binding);
        shell.evaluate(maliciousScript);  // 执行恶意脚本
    }
}

此示例展示了一个脚本注入攻击的场景。用户传入的脚本不仅包含了计算逻辑,还包含了恶意代码——删除系统中的所有文件。如果没有对用户输入的脚本进行校验,攻击者可以轻易地利用 GroovyShell 执行恶意操作。

第四章、CompilerConfiguration 用法及防范

GroovyShell 是 Groovy 中用于动态执行脚本的强大工具,但它也存在潜在的安全隐患,尤其是当它允许执行任意代码时,比如攻击者可能会利用 Runtime.getRuntime().exec() 来执行恶意代码。因此,我们可以通过 CompilerConfiguration 来防止代码注入。

Groovy 的 CompilerConfiguration 提供了一些配置方法,用于限制和管理 Groovy 脚本的编译过程。通过合理的配置,可以大大降低 GroovyShell 代码注入的风险。

4.1 CompilerConfiguration 的基本用法

CompilerConfiguration 类提供了一些可定制的配置选项,允许开发者限制 GroovyShell 的行为。以下是一些常用的配置函数:

  • setScriptBaseClass(String baseClass):设置一个 Groovy 脚本的基础类。
  • setSourceEncoding(String encoding):设置源文件的编码格式。
  • setTargetDirectory(String dir):设置编译后的字节码输出目录。
  • setClasspath(String classpath):设置编译时的类路径。
  • addCompilationCustomizers(CompilationCustomizer... customizers):可以向编译器添加自定义的编译器插件。

4.2 防止危险代码注入:限制 GroovyShell 执行权限

要防止恶意代码通过 GroovyShell 执行,比如 Runtime.getRuntime().exec() 这样的命令注入攻击,我们可以使用 CompilerConfiguration 来限制脚本的访问。

具体的防御策略包括:

  1. 限制允许的类。
  2. 限制脚本中可以执行的特定方法。

攻击场景示例:利用 Runtime.getRuntime().exec() 进行代码注入

攻击者可以通过以下代码进行恶意攻击:

Runtime.getRuntime().exec("rm -rf /")

这是典型的代码注入攻击,攻击者可能利用此命令删除系统中的文件或执行其他恶意操作。

4.3 使用 CompilerConfiguration 防范代码注入

我们可以使用 CompilerConfiguration 配置自定义安全策略,防止恶意代码的执行。下面是一个基本的防范示例:

防范示例:限制 Runtime 类的使用

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import groovy.lang.Script;
import org.codehaus.groovy.control.CompilerConfiguration;
import org.codehaus.groovy.control.customizers.ImportCustomizer;

public class GroovyShellSecurityExample {

    public static void main(String[] args) {
        // 创建编译器配置
        CompilerConfiguration config = new CompilerConfiguration();

        // 使用 ImportCustomizer 限制导入
        ImportCustomizer importCustomizer = new ImportCustomizer();
        importCustomizer.addStarImports("java.util");  // 只允许导入java.util包
        config.addCompilationCustomizers(importCustomizer);

        // 禁止危险类
        config.setScriptBaseClass("groovy.lang.Script");
        Binding binding = new Binding();

        // 创建GroovyShell实例
        GroovyShell shell = new GroovyShell(binding, config);

        // 正常执行Groovy脚本
        String safeScript = "def list = [1, 2, 3]; return list.size()";
        Object result = shell.evaluate(safeScript);
        System.out.println("正常脚本结果: " + result);

        // 尝试执行恶意脚本(会被拦截)
        try {
            String unsafeScript = "Runtime.getRuntime().exec('rm -rf /')";
            shell.evaluate(unsafeScript);
        } catch (Exception e) {
            System.out.println("危险代码被拦截: " + e.getMessage());
        }
    }
}

解释:

  1. ImportCustomizer:我们使用 ImportCustomizer 来控制可以导入的类和包。例如,限制只允许使用 java.util 包内的类,这样可以有效防止 Runtime.getRuntime() 的调用。
  2. ScriptBaseClass:设置基本类,使得自定义的安全策略能够控制脚本执行。
  3. 异常处理:尝试执行危险脚本时,会抛出异常,证明拦截生效。

执行结果:

正常脚本结果: 3
危险代码被拦截: java.lang.SecurityException: No such property: Runtime for class: Script1

4.4 允许正常的脚本调用

我们在实际应用中需要允许某些安全的脚本正常运行,比如简单的数学运算、集合操作等。使用 CompilerConfiguration 可以灵活配置允许的脚本行为。

示例:允许合法的 list 操作

String safeScript = "def list = [1, 2, 3]; return list.size()";
Object result = shell.evaluate(safeScript);
System.out.println("正常脚本结果: " + result);

执行结果:

正常脚本结果: 3

这说明 list 的操作是允许的,因为它不涉及任何危险的操作。

4.5 结合白名单策略增强安全性

为了确保系统安全,我们还可以结合白名单策略,只允许指定包或类的方法执行。如下所示:

限制导入的类并仅允许指定的方法

import org.codehaus.groovy.control.customizers.SecureASTCustomizer;

SecureASTCustomizer secure = new SecureASTCustomizer();

// 禁用所有系统级调用
secure.setImportsBlacklist(Arrays.asList("java.lang.Runtime"));
secure.setMethodDefinitionAllowed(false);  // 禁止定义新的方法

config.addCompilationCustomizers(secure);

这种方式可以有效避免不必要的类和方法的调用,确保只允许执行安全的代码。

4.6 GroovyShell 结合 CompilerConfiguration 优化安全策略总结

  • 限制导入的包和类:通过 ImportCustomizer 控制允许哪些类和包被导入。
  • 禁用危险方法:通过 SecureASTCustomizer 禁止危险方法(如 Runtime)的使用。
  • 自定义白名单:结合业务需求,创建允许的操作白名单,防止不必要的权限泄漏。

SecurityManager 是 Java 的一种安全机制,用于限制 Java 应用程序的权限,防止应用程序执行危险操作。通过自定义 SecurityManager,你可以控制应用程序在执行过程中对系统资源的访问权限。

第五章、SecurityManager 用法及防范

5.1 用法

  1. checkPermission(Permission perm)
    • 检查调用者是否拥有指定权限。如果没有权限,将抛出 SecurityException
    • 这是 SecurityManager 的核心方法,大多数检查操作都会调用它。
  2. checkRead(String file)checkWrite(String file)
    • 检查是否有读取或写入文件的权限。
    • 用于限制文件系统访问。
  3. checkExec(String cmd)
    • 检查是否有执行系统命令的权限(例如 Runtime.getRuntime().exec())。
    • 可用于防止恶意代码执行操作系统命令。
  4. checkConnect(String host, int port)
    • 检查是否有连接到指定主机和端口的权限。
    • 可用于限制网络访问,防止代码与外部服务器通信。
  5. checkDelete(String file)
    • 检查是否有删除文件的权限。
  6. checkExit(int status)
    • 检查是否允许调用 System.exit() 结束 Java 虚拟机。
    • 可用于防止程序恶意终止。
  7. checkPropertyAccess(String key)
    • 检查是否允许访问系统属性。
    • 防止代码读取或修改关键系统设置。
  8. checkPackageAccess(String packageName)
    • 检查是否有访问指定 Java 包的权限。
    • 可用于防止反射访问敏感的 Java 类。
  9. checkCreateClassLoader()
    • 检查是否允许创建类加载器。
    • 防止恶意代码动态加载并执行任意类。
      当使用 GroovyShell 执行动态脚本时,可能会遇到恶意代码执行系统命令、访问文件系统等危险操作。下面我们来演示如何使用 SecurityManager 防止这些问题。

5.2 攻击代码示例

假设攻击者尝试通过 GroovyShell 执行以下恶意代码:

Runtime.getRuntime().exec("rm -rf /");

这个代码将尝试删除系统中的所有文件。

解决方案:自定义 SecurityManager

通过自定义 SecurityManager,我们可以阻止此类操作。下面是一个简单的 SecurityManager 示例,用于防止执行系统命令和其他危险操作。

代码示例

import java.security.Permission;

public class CustomSecurityManager extends SecurityManager {

    @Override
    public void checkPermission(Permission perm) {
        // Allow everything by default
    }

    @Override
    public void checkPermission(Permission perm, Object context) {
        // Allow everything by default
    }

    @Override
    public void checkExec(String cmd) {
        throw new SecurityException("Execution of system commands is not allowed!");
    }

    @Override
    public void checkExit(int status) {
        throw new SecurityException("System exit is not allowed!");
    }

    @Override
    public void checkRead(String file) {
        // Allow read access to non-sensitive files
        if (file.contains("sensitive_data")) {
            throw new SecurityException("Reading sensitive data is not allowed!");
        }
    }

    @Override
    public void checkWrite(String file) {
        // Block write access to certain files
        if (file.contains("/system") || file.contains("/etc")) {
            throw new SecurityException("Writing to system directories is not allowed!");
        }
    }

    @Override
    public void checkConnect(String host, int port) {
        // Allow connections only to internal networks
        if (!host.startsWith("192.168.") && !host.startsWith("localhost")) {
            throw new SecurityException("External network connections are not allowed!");
        }
    }

    // Other methods can also be overridden for specific use cases...
}

使用 SecurityManager 的完整示例

import groovy.lang.GroovyShell;
import java.security.Permission;

public class SecureGroovyExecution {

    public static void main(String[] args) {
        // Set custom SecurityManager
        System.setSecurityManager(new CustomSecurityManager());

        GroovyShell shell = new GroovyShell();
        
        String maliciousScript = "Runtime.getRuntime().exec('rm -rf /')";
        try {
            shell.evaluate(maliciousScript);
        } catch (SecurityException se) {
            System.out.println("Security exception caught: " + se.getMessage());
        } finally {
            // Remove security manager after execution
            System.setSecurityManager(null);
        }
    }
}

优化后的代码防范成功

在这段代码中,CustomSecurityManager 对系统命令执行 (Runtime.getRuntime().exec) 和系统退出 (System.exit) 进行了限制。当尝试执行恶意代码时,会抛出 SecurityException,并阻止操作。

  • 防范机制:当 Groovy 脚本尝试调用 Runtime.getRuntime().exec() 时,CustomSecurityManager 中的 checkExec 方法会被触发,从而阻止系统命令的执行。
  • 效果:系统命令执行被成功拦截,恶意代码无法对系统产生影响。

攻击与防范流程

  1. 攻击代码:攻击者试图在 Groovy 脚本中执行危险的系统命令。
  2. 安全检查:自定义的 SecurityManager 拦截了 exec 调用。
  3. 防范成功:系统抛出 SecurityException,并显示错误信息,提示执行系统命令的尝试被阻止。

5.3 进一步的安全措施

  1. 限制类加载
    • 通过 checkCreateClassLoader() 限制脚本动态加载类,防止加载未知代码。
  2. 控制网络访问
    • 通过 checkConnect() 限制脚本的网络访问权限,防止脚本向外部服务器发送数据。
  3. 限制反射操作
    • 通过 checkPackageAccess() 限制访问 java.lang.reflect.*,防止脚本使用反射访问私有方法或字段。

5.4 允许特定包和方法调用

为了进一步增强灵活性,可以扩展 SecurityManager,允许特定包下的类或方法调用,而继续限制危险操作。

@Override
public void checkPackageAccess(String packageName) {
    if (!packageName.startsWith("java.util") && !packageName.startsWith("groovy")) {
        throw new SecurityException("Access to this package is not allowed!");
    }
}

通过这样的扩展,可以允许 java.utilgroovy 包下的操作,而阻止访问其他敏感包。

第六章、使用脚本沙箱(Script Sandbox)

Groovy 社区提供了一个安全沙箱库,可以限制脚本的执行权限。通过这个沙箱,我们可以精细化控制脚本中允许使用的对象、方法和类。对于关键业务场景,建议使用 Groovy 的 groovy-sandbox 库来严格控制脚本的执行权限。

代码示例:使用 Groovy Sandbox 来限制脚本权限

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import org.kohsuke.groovy.sandbox.GroovyInterceptor;
import org.kohsuke.groovy.sandbox.SandboxedGroovyShell;
import org.kohsuke.groovy.sandbox.SandboxTransformer;

public class GroovySandboxExample {
    public static void main(String[] args) {
        // 1. 创建沙箱转换器
        SandboxTransformer sandboxTransformer = new SandboxTransformer();
        
        // 2. 创建 Sandboxed GroovyShell
        GroovyShell shell = new SandboxedGroovyShell(new Binding());
        shell.getClassLoader().addCompilationCustomizers(sandboxTransformer);
        
        // 3. 添加自定义的 GroovyInterceptor,限制脚本中的 API 调用
        GroovyInterceptor.register(new SafeInterceptor());

        // 4. 执行脚本
        String script = "Runtime.getRuntime().exec('rm -rf /');";
        try {
            Object result = shell.evaluate(script);  // 这段代码会被拦截
            System.out.println(result);
        } catch (Exception e) {
            System.out.println("Script execution blocked: " + e.getMessage());
        }
    }
}

// 自定义拦截器,限制对危险类和方法的访问
class SafeInterceptor extends GroovyInterceptor {
    @Override
    public Object onMethodCall(GroovyInterceptor.Invoker invoker, Object receiver, String method, Object[] args) throws Throwable {
        // 拦截对 Runtime.getRuntime().exec 的调用
        if (receiver instanceof Runtime && "exec".equals(method)) {
            throw new SecurityException("Runtime.exec is not allowed!");
        }
        return super.onMethodCall(invoker, receiver, method, args);
    }
}

解释:

  1. Groovy Sandbox:使用 groovy-sandbox 库,通过沙箱模式拦截并控制脚本执行时的所有方法调用。在这个例子中,脚本试图调用 Runtime.getRuntime().exec() 会被拦截器阻止,从而防止恶意代码的执行。
  2. 自定义拦截器(GroovyInterceptor):我们可以定义自己的拦截器 SafeInterceptor,用于拦截脚本中的危险方法调用,如 exec()。如果检测到不安全的操作,抛出 SecurityException 并阻止该操作。

第七章、静态代码审查

除了动态拦截之外,开发者还可以对用户提交的脚本进行静态分析,检测其中是否包含可疑或危险的代码。Groovy 提供了编译时的 AST 变换(Abstract Syntax Tree),可以通过它分析脚本中的结构和语义,找到潜在的安全问题。

import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.MethodNode;
import org.codehaus.groovy.control.CompilationUnit;
import org.codehaus.groovy.control.CompilerConfiguration;

public class StaticCodeAnalysis {
    public static void main(String[] args) {
        CompilerConfiguration config = new CompilerConfiguration();
        CompilationUnit cu = new CompilationUnit(config);
        
        cu.addPhaseOperation(sourceUnit -> {
            for (ClassNode classNode : sourceUnit.getAST().getClasses()) {
                for (MethodNode methodNode : classNode.getMethods()) {
                    if (methodNode.getCode().getText().contains("Runtime.getRuntime().exec")) {
                        throw new SecurityException("Unsafe method found in script!");
                    }
                }
            }
        }, CompilationUnit.SEMANTIC_ANALYSIS);

        cu.addSource("example.groovy", "Runtime.getRuntime().exec('rm -rf /');");
        
        try {
            cu.compile();
        } catch (Exception e) {
            System.out.println("Script failed static analysis: " + e.getMessage());
        }
    }
}

解释:

  • 静态分析:该示例展示了如何在脚本编译过程中对其进行静态分析。如果检测到脚本中包含不安全的调用,如 Runtime.getRuntime().exec(),则会抛出异常,阻止脚本执行。

第八章、资源滥用

在电商交易系统中,脚本可能会消耗大量资源,如 CPU、内存等,导致系统性能下降。

解决方案

  • 限制脚本执行时间:可以使用 ExecutorService 来限制脚本的执行时间,避免脚本长时间占用资源。
  • 资源隔离:通过容器化或虚拟化技术,隔离脚本执行环境,避免脚本占用系统的全部资源。

代码示范

import groovy.lang.Binding;
import groovy.lang.GroovyShell;
import org.codehaus.groovy.control.CompilerConfiguration;

public class SecureGroovyShellExample {
    public static void main(String[] args) {
        // 限制脚本执行的配置
        CompilerConfiguration config = new CompilerConfiguration();
        config.setScriptBaseClass("SecureScript");  // 设置安全基类

        // 设置 Binding, 将安全相关的上下文变量传入脚本
        Binding binding = new Binding();
        binding.setVariable("orderAmount", 1000);
        binding.setVariable("userType", "VIP");

        // 自定义 GroovyShell 配置
        GroovyShell shell = new GroovyShell(binding, config);
        String script = "if (userType == 'VIP') { return orderAmount * 0.8 } else { return orderAmount }";

        Object result = shell.evaluate(script);

        System.out.println("Final price: " + result);  // 输出:Final price: 800.0
    }
}

定义安全基类

为确保脚本执行过程中无法访问危险的系统资源,我们可以自定义一个安全基类 SecureScript,在此基类中禁用某些不安全的方法和操作。

import groovy.lang.Script;

public abstract class SecureScript extends Script {
    @Override
    public Object run() {
        // 禁用 Runtime 调用
        throw new UnsupportedOperationException("Unsafe operations are not allowed!");
    }
}

通过继承 Script 并覆盖 run() 方法,我们有效防止了脚本中使用诸如 Runtime.getRuntime().exec() 等危险的系统调用。此外,可以进一步扩展 SecureScript 以禁用更多可能导致资源滥用或泄露的操作。

限制 GroovyShell 执行的类和方法

除了自定义安全基类,还可以进一步通过 CompilerConfiguration 配置 GroovyShell 的行为。以下是如何禁止某些类或方法的示例:

config.setScriptBaseClass("SecureScript");
config.addCompilationCustomizers(new ImportCustomizer().addStarImports("java.util").addStaticStars("Math"));

在这个配置中,我们只允许脚本使用 java.util 包和 Math 的静态方法,其它不必要的系统资源则无法访问。

执行超时限制

为了防止脚本长时间占用系统资源,我们可以使用 ExecutorService 来限制脚本的执行时间。

import java.util.concurrent.*;

public class TimeoutGroovyShellExample {
    public static void main(String[] args) throws InterruptedException, ExecutionException, TimeoutException {
        ExecutorService executor = Executors.newSingleThreadExecutor();
        Future<Object> future = executor.submit(() -> {
            GroovyShell shell = new GroovyShell();
            return shell.evaluate("Thread.sleep(5000); return 'Completed';");  // 模拟耗时任务
        });

        try {
            Object result = future.get(2, TimeUnit.SECONDS);  // 设定超时时间为 2 秒
            System.out.println("Result: " + result);
        } catch (TimeoutException e) {
            System.out.println("Script execution timed out.");
        } finally {
            executor.shutdown();
        }
    }
}

在此示例中,若脚本执行时间超过 2 秒,TimeoutException 会被抛出,并及时终止脚本执行,确保系统不会因脚本长时间运行而遭受影响。

第九章、总结

GroovyShell 是一款非常强大的工具,能够为 Java 应用带来极大的灵活性,特别是在电商交易系统等需要动态业务逻辑的场景下,GroovyShell 可以帮助开发者快速实现需求。然而,动态执行脚本也存在一定的安全风险,如脚本注入、资源滥用等。
在实际开发中,务必要为动态执行脚本的功能增加足够的安全保护措施,避免潜在的攻击或系统资源滥用问题。通过安全的 GroovyShell 实践,可以使系统更具灵活性,同时保证其健壮性和安全性。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

多层建筑能源参数化模型和城市冠层模型的区别

多层建筑能源参数化&#xff08;Multi-layer Building Energy Parameterization, BEP&#xff09;模型和城市冠层模型&#xff08;Urban Canopy Model, UCM&#xff09;都是用于模拟城市环境中能量交换和微气候的数值模型&#xff0c;但它们的侧重点和应用场景有所不同。以下是…

MongoDB事务机制

事务机制 1.事务概念 在对数据的操作的过程中&#xff0c;涉及到一连串的操作&#xff0c;这些操作如果失败&#xff0c;会导致我们的数据部分变化了&#xff0c;部分没变化。这个过程就好比如你去吃早餐&#xff0c;你点完餐了&#xff0c;并且吃完早餐了&#xff0c;没付钱你…

【文件包含】——日志文件注入

改变的确很难&#xff0c;但结果值得冒险 本文主要根据做题内容的总结&#xff0c;如有错误之处&#xff0c;还请各位师傅指正 一.伪协议的失效 当我们做到关于文件包含的题目时&#xff0c;常用思路其实就是使用伪协议&#xff08;php:filter,data,inpput等等&#xff09;执行…

职业技能大赛背景下的移动互联网应用软件开发(Android)实训室建设方案

一、建设背景 随着科技的持续进步&#xff0c;移动设备已成为人们日常生活中不可或缺的一部分。据相关数据&#xff0c;移动互联网的使用率在近年来显著上升。在这样的背景下&#xff0c;移动互联技术不仅推动了科技的发展&#xff0c;也渗透到了智能家居、车联网、工业自动化…

TESSY创建需要手写桩的测试用例

如果需要让桩函数有额外的功能&#xff0c;如&#xff1a;传参检测、局部数据处理、多传参检测、函数实现变更等&#xff0c;可以进行手写桩。 我们以tessy5.1 IDE为例&#xff0c;给大家展示编写一个需要手写桩的测试用例过程。 1、前期的准备工作 可以参考以下文章&#xff1…

Qt常用控件——QTextEdit

文章目录 QTextEdit核心属性和信号同步显示示例信号示例 QTextEdit核心属性和信号 QTextEdit表示多行输入框&#xff0c;是一个富文本和markdown编辑器&#xff0c;并且能在内存超出编辑框范围时自动提供滚动条。 QPlainTexEdit是纯文本&#xff0c;QTextEdit不仅表示纯文本&a…

记得忘记密码情况下如何退出苹果Apple ID

在日常使用苹果手机时&#xff0c;我们可能会遇到需要退出Apple ID的情况&#xff0c;比如更换手机、不再使用某些服务或出于安全考虑等。下面&#xff0c;我们就来详细介绍一下苹果手机如何退出Apple ID。 情况一&#xff1a;记得Apple ID密码 若是记得Apple ID密码&#xff…

Tomcat服务详解

一、部署Tomcat服务器 JDK安装官方网址&#xff1a;https://www.oracle.com/cn/java Tomcat安装官方网址&#xff1a;Apache Tomcat - Welcome! 安装JDK 1.获取安装包 wget https://download.oracle.com/otn/java/jdk/8u411-b09/43d62d619be4e416215729597d70b8ac/jdk-8u41…

透明任务栏怎么设置?Windows电脑任务栏透明效果(详尽指南)

电脑任务栏可以自定义调整透明度&#xff0c;在Windows10和Windows11系统中&#xff0c;任务栏透明是默认不透明的。如果想要设置任务栏透明度&#xff0c;那么推荐以下方法实现&#xff0c;简单三个步骤即可实现&#xff0c;一起来看看吧&#xff01; 第一步、选择合适的任务栏…

基于鸿蒙API10的RTSP播放器(五:拖动底部视频滑轨实现跳转)

拖动前播放位置&#xff1a; 拖动后播放位置&#xff1a; 在Slider组件中&#xff0c;添加onChange方法进行监听&#xff0c;当视频轨道拖放结束时&#xff0c;触发this.seekTo()函数&#xff0c;其中seekTo函数需要传递一个视频已播放时长作为参数 Slider({ value: this.p…

【iOS】push和present的区别

【iOS】push和present的区别 文章目录 【iOS】push和present的区别前言pushpop presentdismiss简单小demo来展示dismiss和presentdismiss多级 push和present的区别区别相同点 前言 在iOS开发中&#xff0c;我们经常性的会用到界面的一个切换的问题&#xff0c;这里我们需要理清…

【专题】2024年8月医药行业报告合集汇总PDF分享(附原数据表)

原文链接&#xff1a;https://tecdat.cn/?p37621 在科技飞速发展的当今时代&#xff0c;医药行业作为关乎人类生命健康的重要领域&#xff0c;正处于前所未有的变革浪潮之中。数智医疗服务的崛起&#xff0c;为医疗模式带来了全新的转变&#xff0c;开启了医疗服务的新时代。…

SQL超时的常见原因和解决思路

目录 1. SQL超时的常见原因2. 解决思路2.1. 优化SQL查询2.2. 处理锁竞争2.3. 网络和连接配置2.4. 资源监控与调整 3. 预防措施4. 示例&#xff1a;设置SQL超时5. 总结 SQL超时问题常常会影响应用程序的性能和用户体验&#xff0c;了解和处理SQL超时的思路非常重要。以下是一些常…

【Oracle篇】全面理解优化器和SQL语句的解析步骤(含执行计划的详细分析和四种查看方式)(第二篇,总共七篇)

&#x1f4ab;《博主介绍》&#xff1a;✨又是一天没白过&#xff0c;我是奈斯&#xff0c;DBA一名✨ &#x1f4ab;《擅长领域》&#xff1a;✌️擅长Oracle、MySQL、SQLserver、阿里云AnalyticDB for MySQL(分布式数据仓库)、Linux&#xff0c;也在扩展大数据方向的知识面✌️…

干部画像系统的意义

干部画像系统是一个高度集成且功能丰富的管理工具&#xff0c;在干部管理、选拔、培养和评价等多个方面发挥着重要作用。显著提升干部管理工作的科学性、准确性和效率性。干部画像系统的意义主要包括&#xff1a; 1、增强干部选拔的精准性 干部画像系统通过全面收集和分析干部…

第15-05章:获取运行时类的完整结构

我的后端学习大纲 我的Java学习大纲 6.1.第一组方法API: 1.API列表&#xff1a;java.lang.Class 类&#xff1a; 2.代码测试&#xff1a; public class ReflectionUtils{ puvblic static void main(String[] args){}// 第一组Testpublic void api_01{//上面截图的代码......…

下载 llama2-7b-hf 全流程【小白踩坑记录】

1、文件转换 在官网 https://ai.meta.com/llama/ 申请一个账号&#xff0c;选择要下载的模型&#xff0c;会收到一个邮件&#xff0c;邮件中介绍了下载方法 执行命令 git clone https://github.com/meta-llama/llama.git​ &#xff0c;然后执行 llama/download.sh&#xff0c…

IP地址是怎么实现HTTPS访问的?

首先&#xff0c;需要明确的是&#xff0c;IP地址&#xff08;Internet Protocol Address&#xff09;是互联网上设备&#xff08;如服务器、路由器等&#xff09;的唯一标识符&#xff0c;它允许数据包在网络中正确地路由和传输。然而&#xff0c;IP地址本身并不直接支持HTTPS…

可测试,可维护,可移植:上位机软件分层设计的重要性

互联网中&#xff0c;软件工程师岗位会分前端工程师&#xff0c;后端工程师。这是由于互联网软件规模庞大&#xff0c;从业人员众多。前后端分别根据各自需求发展不一样的技术栈。那么上位机软件呢&#xff1f;它规模小&#xff0c;通常一个人就能开发一个项目。它还有必要分前…

中国水土保持能力防治数据集(1992-2019)

该数据集包括1992年至2019年中国每年的水土保持能力及其影响因子。这些数据是基于改进的RUSLE模型开发的&#xff0c;其中包含植被覆盖和管理(C)因子和降雨侵蚀率(R)因子作为重要的输入因子&#xff0c;针对不同区域进行了优化。 其中该数据集一共包含了9个数据它们分别是&…