【毕设扫描器】【参数Fuzz】第一篇:数据的定义、读取和装配(爬虫数据和Payload数据)

本文主要是介绍【毕设扫描器】【参数Fuzz】第一篇:数据的定义、读取和装配(爬虫数据和Payload数据),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

文章目录

    • 字典文件的数据结构
    • 读取嵌套的 Json 数据
        • 读取值为基本数据类型的Json文件
        • 读取值为数组的Json数据
        • 读取值为字典的Json文件
        • 读取包含两个层级键名的Json文件
    • 准备数据阶段
        • 修改爬虫保存结果(结合报错和实际情况未修改代码,可忽略)
        • 从 Json 文件读取需要的爬虫数据
        • 读取 paramsFuzz.json 文件
    • 装配数据阶段
        • 配置请求对象 req
        • 保存传递动态参数的 Url 信息
        • 装配数据
            • 第一步
            • 第二步
            • 第三四五步
    • 执行阶段
    • 接收结果并验证阶段

字典文件的数据结构

在项目根目录创建 fuzzDicts 目录,创建 fuzzDicts/params.json,用于测试参数。(使用 json 是因为常见/易读/复用性强)

参数测试Payload格式:不同的漏洞类型、漏洞类型下不同的软件系统、对应Payload。

一级数据是漏洞类型,如 SQLI、XSS等,数据结构是字典格式。(添加字段 description 描述payload,不需要专门使用一个字段进行分类。该部分是在读取 Json 文件时进行的修改)

二级数据是漏洞类型的下一级数据,可能需要根据不同软件类型选择 Payload,所以也要使用字典格式。二级数据如果不分软件类型,则定义键名为 universal(还要单独输入一个字段,而大多数情况都不知道软件类型,还是要枚举测试所有Payload,所以该字段不是很有必要)

二级数据是Payload,根据不同Payload需要选择不同的响应判断,如时间延迟注入的响应时间、响应内容中的关键字,所以使用字典格式。(Payload直接作为污染参数数据的键名即可)(实际读取 Json 文件时做出的优化)

一级数据是一个键 data,其键值是数据类型,用于存储 payload 的字典信息。

二级数据是最底层的数据,注入参数可能有很多、响应时间是整数、关键词是字符串等,所以根据实际需要分别使用 List、Int、String等数据类型。

未考虑的场景问题

  • 根据比较不同Payload下返回的响应信息来判断漏洞是否存在。

排版如下。

{"data":[{"description": "SQLI-001: MySQL-数字型延迟注入","payload": "/**/and/**/sleep(5)","time": 5,"keyword": ""},{"description": "SQLI-002: MySQL-字符型延迟注入","payload": "'/**/and/**/sleep(5)--+","time": 5,"keyword": ""},{"description": "SQLI-003: MySQL-字符型延迟注入","payload": "\"/**/and/**/sleep(5)--+","time": 5,"keyword": ""},{"description": "SQLI-004: MySQL-报错注入","payload": "'\"+,","keyword": "You have an error in your SQL syntax"},{"description": "XSS-001: 跨站脚本攻击漏洞""payload": "<script>alert(/xss/)</script>","keyword": "xxx"}]}

读取嵌套的 Json 数据

读取值为基本数据类型的Json文件

这里的单层是指,Json数据的值是基本数据类型,不是列表、字典等数据结构。

创建 test.json 文件,文件内容如下。

{"name": "pumpkin","date": "2022-04-05"
}

查找网上文章 Go 对象序列化 等,编写读取Json文件代码。

  • 读取配置文件的字节数据:bytesJSON, err := ioutil.ReadFile(“example.json”)

  • go 内置对 json 数据的处理包是 encoding/json

  • 把字节数据解析成Json编码数据:json.Unmarshal

  • 接收Json数据:需要事先定义一个结构体

成功运行解析的代码和打印结果如下。

/* 打印结果pumpkin2022-04-05
*///定义配置文件解析后的结构
type Test struct {Name	string 	`json:"name"`Date	string `json:"date"`
}func main() {var test Testbytes, err := ioutil.ReadFile("./test.json")if err != nil {fmt.Println("读取json文件失败", err)return}err = json.Unmarshal(bytes, &test)if err != nil {fmt.Println("解析数据失败", err)return}fmt.Println(test.Name)fmt.Println(test.Date)
读取值为数组的Json数据

test.json 配置文件的内容如下。

此时使用上一小节读取基本数据类型的代码,json.Unmarshal(bytes, &test) 会报错并退出程序,无法把数组结构解析成 Go 结构体的 string 类型:
解析数据失败 json: cannot unmarshal array into Go struct field Test.name of type string

{"name": ["pumpkin", "watermelon"],"date": "2022-04-05"
}

修改结构体的参数类型为字符串数组:[]string。运行成功且打印结果如下。

/*	打印结果[pumpkin watermelon]2022-04-05
*/
//定义配置文件解析后的结构
type Test struct {Name	[]string 	`json:"name"`Date	string 		`json:"date"`
}
读取值为字典的Json文件

参考文章 golang 数据三 (字典),golang基本数据结构Map也叫字典,字典的声明格式是:map[KeyType]ValueType

此时 test.json 配置文件的内容如下。

{"name": ["pumpkin", "watermelon"],"date": "2022-04-05""sex":{"man":1,"woman":0}
}

定义接收 Json 数据的结构体如下,成功读取并打印 Json 数据内容。

//定义配置文件解析后的结构
type Test struct {Name	[]string 		`json:"name"`Date	string 			`json:"date"`Sex 	map[string]int	`json:"sex"`
}// main()函数中的操作代码
func main() {var test Testbytes, err := ioutil.ReadFile("./test.json")if err != nil {fmt.Println("读取json文件失败", err)return}err = json.Unmarshal(bytes, &test)if err != nil {fmt.Println("解析数据失败", err)return}fmt.Println(test.Name)fmt.Println(test.Date)fmt.Println("man: ", test.Sex["man"])fmt.Println("woman: ", test.Sex["woman"])
}
读取包含两个层级键名的Json文件

此时 test.json 配置文件的内容如下。

{"req_list": [{"url": "http://127.0.0.1/sqli-labs-master/Less-1/?id=1","method": "GET","headers": {"Spider-Name": "crawlergo","User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.0 Safari/537.36"},"data": "","source": "Target"}],"all_req_list": [{"url": "http://127.0.0.1/sqli-labs-master/Less-1/?id=1","method": "GET","headers": {"Spider-Name": "crawlergo","User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.0 Safari/537.36"},"data": "","source": "Target"}],"all_domain_list": ["127.0.0.1"],"sub_domain_list": ["127.0.0.1"]

尝试定义 req_list 的值为数组 array,json.Unmarshal() 函数报错:解析数据失败 json: cannot unmarshal object into Go struct field Crawler.req_list of type string。

type Crawler struct {ReqList         []string `json:"req_list"`AllReqList      []string `json:"all_req_list"`AllDomainList 	[]string `json:"all_domain_list"`SubDomainList 	[]string `json:"sub_domain_list"`
}

数组的元素值类型应该是字典 map,尝试定义如下结构体,仍然是相同的报错信息。

type Crawler struct {ReqList         []map[string]string `json:"req_list"`AllReqList      []map[string]string `json:"all_req_list"`AllDomainList 	[]map[string]string `json:"all_domain_list"`SubDomainList 	[]map[string]string `json:"sub_domain_list"`
}

由于 Json 文件包含不同层级的键名,所以定义结构体的结构也肯定不同,参考文章:Go 解析嵌套 json。

如果 Json 数据有多层键,那么每层键都需要定义一个结构体接收对应的键名,并且定义变量时需要嵌套结构体类型。

查看参考文章编写代码,成功读取嵌套 Json 文件的代码和打印结果如下。

/*	打印结果http://127.0.0.1/sqli-labs-master/Less-1/?id=1GETSpider-Name crawlergoUser-Agent Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.0 Safari/537.36
*/
// 接收第一层 Json 数据
type CrawlerFirst struct {ReqList			[]CrawlerSecond			`json:"req_list"`AllReqList      []CrawlerSecond 		`json:"all_req_list"`AllDomainList 	[]string 				`json:"all_domain_list"`SubDomainList 	[]string 				`json:"sub_domain_list"`
}type CrawlerSecond struct {Url			string						`json:"url"`Method      string 						`json:"method"`Headers 	map[string]string 			`json:"headers"`Data 		string 						`json:"data"`Source 		string						`json:"source"`
}// Test 定义配置文件解析后的结构
type Test struct {Name	[]string 		`json:"name"`Date	string 			`json:"date"`Sex 	map[string]int	`json:"sex"`
}func main() {//var req model.Requestvar crawlerFirst CrawlerFirstbytes, err := ioutil.ReadFile("./debug.json")if err != nil {fmt.Println("读取json文件失败", err)return}err = json.Unmarshal(bytes, &crawlerFirst)if err != nil {fmt.Println("解析数据失败", err)return}for _,req:= range crawlerFirst.ReqList{fmt.Println(req.Url)fmt.Println(req.Method)fmt.Println(req.Data)for key,value:= range req.Headers {fmt.Println(key, value)}}}

准备数据阶段

修改爬虫保存结果(结合报错和实际情况未修改代码,可忽略)

读取爬虫结果的前提是,爬虫结果是我们需要的数据。原项目中把如下 4 种数据保存到一个 Json 文件,我们首先需要分离这些数据,使每种数据分别保存到各自的文件。

type Result struct {ReqList       []Request `json:"req_list"`AllReqList    []Request `json:"all_req_list"`AllDomainList []string  `json:"all_domain_list"`SubDomainList []string  `json:"sub_domain_list"`
}

crawlergo_cmd.go 文件保存结果的相关代码,调试打印 result 变量值发现,此时爬虫结果按照 Result 结构体都已经填充内容。先酱紫,后续对爬虫结果结构体有想法,再另外进行修改。

考虑到报错、以及直接可以读取 Json 文件,不修改代码。

	// 代码 350 行// 输出结果outputResult(result)// 代码 403 行
func outputResult(result *pkg.Result) {// 输出结果if outputMode == "json" {fmt.Println("--[Mission Complete]--")resBytes := getJsonSerialize(result)fmt.Println(string(resBytes))} else if outputMode == "console" {for _, req := range result.ReqList {req.FormatPrint()}}// 写入文件的主要代码if len(outputJsonPath) != 0 {resBytes := getJsonSerialize(result)tools.WriteFile(outputJsonPath, resBytes)}// 修改该部分主要代码为如下内容(不更改代码,直接读取 json 文件)/*注意,1.结构体中的变量名需要开启调试查看、或从其他代码中找到2.序列化结构体的变量时,报错如下。在结构体定义代码中,前两个变量的类型是 []Request,域名变量是 []string考虑到可以直接读取Json文件,不更改代码。cannot use result.ReqList (type []*model.Request) as type *pkg.Result in argument to getJsonSerializecannot use result.AllDomainList (type []string) as type *pkg.Result in argument to getJsonSerialize*/if len(outputJsonPath) != 0 {resBytes1 := getJsonSerialize(result.req_list)resBytes2 := getJsonSerialize(result.all_req_list)resBytes3 := getJsonSerialize(result.all_domain_list)resBytes4 := getJsonSerialize(result.sub_domain_list)tools.WriteFile("req_" + outputJsonPath, resBytes1)tools.WriteFile("all_req_" + outputJsonPath, resBytes2)tools.WriteFile("all_domain_" + outputJsonPath, resBytes3)tools.WriteFile("sub_domain_" + outputJsonPath, resBytes4)}}
从 Json 文件读取需要的爬虫数据

关于嵌套 Json 文件数据的读取,在本文的上一章节《读取嵌套的 Json 数据》已完成了代码的编写和调试。

读取数据的任务完成了,Fuzz 需要用到哪些数据呢?

url
method
headers	// 为了避免被反爬虫限制访问,必须使用合适的请求头
data

读取爬虫Json文件

// 接收第一层 Json 数据
type CrawlerFirst struct {ReqList			[]CrawlerSecond			`json:"req_list"`AllReqList      []CrawlerSecond 		`json:"all_req_list"`AllDomainList 	[]string 				`json:"all_domain_list"`SubDomainList 	[]string 				`json:"sub_domain_list"`
}type CrawlerSecond struct {Url			string						`json:"url"`Method      string 						`json:"method"`Headers 	map[string]string 			`json:"headers"`Data 		string 						`json:"data"`Source 		string						`json:"source"`
}// 封装函数
func read_crawler() CrawlerFirst{var crawlerFirst CrawlerFirstbytes, err := ioutil.ReadFile("./debug.json")if err != nil {fmt.Println("读取json文件失败", err)os.Exit(1)}err = json.Unmarshal(bytes, &crawlerFirst)if err != nil {fmt.Println("解析数据失败", err)os.Exit(1)}return crawlerFirst
}
读取 paramsFuzz.json 文件

读取代码改了又改,总是报错。无奈从基本数据类型开始编写 Json 文件进行读取,然后逐渐嵌套数据并完成读取 Json 数据,最终代码和打印结果如下。

读取的 Json 文件见本文第一章 字典文件的数据结构

/* 打印 sqli 键值的结果
//	/**/and/**/sleep(5)
//	MySQL-数字型延迟注入
//	5//	'/**/and/**/sleep(5)--+
//	MySQL-字符型延迟注入
//	5//	"/**/and/**/sleep(5)--+
//	MySQL-字符型延迟注入
//	5//	'"+,
//	MySQL-报错注入
//	0
//	You have an error in your SQL syntax
*/// 定义配置文件解析后的结构
type ParamsFuzzJson struct {SqlInjection	[]ParamData		`json:"sqli"`Xss				[]ParamData		`json:"xss"`
}type ParamData struct {Payload 	string		`json:"payload"`Description string 		`json:"description"`Time 		int			`json:"time"`Keyword		string		`json:"keyword"`
}func main() {//var req model.Requestvar paramsFuzzJson ParamsFuzzJsonbytes, err := ioutil.ReadFile("./fuzzDicts/paramsFuzz.json")if err != nil {fmt.Println("读取json文件失败", err)// os.Exit(1)return}err = json.Unmarshal(bytes, &paramsFuzzJson)if err != nil {fmt.Println("解析数据失败", err)return//os.Exit(1)}// fmt.Println(paramsFuzzJson.SqlInjection)// 读取 Json 的 sqli 键for _, param:= range paramsFuzzJson.SqlInjection{// for _,param:= range param.key{fmt.Println(param.Payload)fmt.Println(param.Description)fmt.Println(param.Time)fmt.Println(param.Keyword)}}

装配数据阶段

配置请求对象 req

项目文件 crawlergo/pkg/model 定义的请求对象结构体包含 8 个变量,考虑只保留如下 5 个变量,重新在 paramsFuzz.go 文件定义请求对象结构体。

type Request struct {URL             *URLMethod          stringHeaders         map[string]interface{}PostData        stringProxy           string
}

明确参数 Fuzz 的需求

  • 遍历 req_list:爬虫结果中 req_list 键的内容,如果存在Get参数或Post参数则进行 Fuzz
  • 遍历 paramJson 中的每一个键:sqli、xss等
保存传递动态参数的 Url 信息

对于爬虫结果,要筛选出传递动态参数的URl进行参数Fuzz测试。

顺便把传递动态参数的Url保存到新的Json文件,方便人工查看,如下代码把传递动态参数的爬虫结果保存到指定文件 params_debug.json。

// 接收第一层 Json 数据
type CrawlerJson struct {ReqList			[]CrawlerData			`json:"req_list"`AllReqList      []CrawlerData 		`json:"all_req_list"`AllDomainList 	[]string 				`json:"all_domain_list"`SubDomainList 	[]string 				`json:"sub_domain_list"`
}type CrawlerData struct {Url			string						`json:"url"`Method      string 						`json:"method"`Headers 	map[string]string 			`json:"headers"`Data 		string 						`json:"data"`Source 		string						`json:"source"`
}// 调用代码
for _,crawler:= range crawlerReq {outputParamsResult(crawler)
}func outputParamsResult(result CrawlerData) {// 写入的文件名变量,在合并代码时需要调整修改outputJsonPath := "debug.json"// 输出结果if len(outputJsonPath) != 0 {resBytes := getParamsJsonSerialize(result)tools.WriteFile("params_" + outputJsonPath, resBytes)}
}func getParamsJsonSerialize(paramsResult CrawlerData) []byte {resBytes, err := json.Marshal(paramsResult)if err != nil {log.Fatal("Marshal result error")}return resBytes
}
装配数据

算法步骤:

  • 准备数据1:读取爬虫结果,调用爬虫结构体的参数信息
  • 准备数据2:读取参数 Fuzz 字典,调用结构体
  • 筛选:遍历爬虫结构体,通过条件判断找出传递动态参数的Url,根据传参方式分为 Get 和 Post
  • 准备数据3:逐个添加 Payload 到动态参数末尾,如果是 Get 方式则拼接 Url 和参数
  • 装配:把爬虫结构体的信息、以及处理后的动态参数信息,装配到请求对象 req
  • 运行和验证:发送请求,查看响应信息验证漏洞是否存在(运行阶段)
  • 标记去重:如果动态参数测试过了,则加入 Array ,并且在测试动态参数前检查是否在 Array 中(验证阶段)
第一步

读取爬虫结果

// 接收第一层 Json 数据
type CrawlerJson struct {ReqList			[]CrawlerData			`json:"req_list"`AllReqList      []CrawlerData 		`json:"all_req_list"`AllDomainList 	[]string 				`json:"all_domain_list"`SubDomainList 	[]string 				`json:"sub_domain_list"`
}type CrawlerData struct {Url			string						`json:"url"`Method      string 						`json:"method"`Headers 	map[string]string 			`json:"headers"`Data 		string 						`json:"data"`Source 		string						`json:"source"`
}func main() {// 1.读取爬虫结果crawlerReq := read_crawlerReq()}func read_crawlerReq() []CrawlerData{var crawlerJson CrawlerJsonbytes, err := ioutil.ReadFile("./debug.json")if err != nil {fmt.Println("读取json文件失败", err)os.Exit(1)}err = json.Unmarshal(bytes, &crawlerJson)if err != nil {fmt.Println("解析数据失败", err)os.Exit(1)}return crawlerJson.ReqList}
第二步

读取参数 Fuzz 的 payload 文件 paramsFuzz.json

// 定义结构体接收参数 Fuzz 的 Json 数据
type ParamsFuzzJson struct {Data			[]ParamData		`json:"data"`
}type ParamData struct {Description string 		`json:"description"`Payload 	string		`json:"payload"`Time 		int			`json:"time"`Keyword		string		`json:"keyword"`
}func main() {// 1.读取爬虫结果crawlerReq := read_crawlerReq()// 2.读取参数 Fuzz 字典/*	功能说明:读取得到一个数组,数组里的元素是 Payload 字典。可以通过遍历数组来逐个读取装配 Payload。调用说明:每次装配 payload 都要绑定一个 request以便使用 payload 字典的关键字等字段判断漏洞是否存在,以及探测漏洞存在后打印 payload 信息也就是说,遍历 payload 数组,是遍历的第一层*/paramsArray := read_paramsPayload()// 遍历 Json 数据中 data 键的键值数组,用于获取每一个 payload 字典for _, payloadDict := range paramsArray.Data {fmt.Println(payloadDict.Payload)}}func read_paramsPayload() ParamsFuzzJson {var paramsFuzzJson ParamsFuzzJsonbytes, err := ioutil.ReadFile("./fuzzDicts/paramsFuzz.json")if err != nil {fmt.Println("读取json文件失败", err)os.Exit(1)}err = json.Unmarshal(bytes, &paramsFuzzJson)if err != nil {fmt.Println("解析数据失败", err)os.Exit(1)}return paramsFuzzJson
}
第三四五步

第三步筛选,遍历爬虫结构体,通过条件判断找出传递动态参数的Url,根据传参方式分为 Get 和 Post。

第四步准备数据3:逐个添加 Payload 到动态参数末尾,然后对URL或者PostData进行字串替换。

第五步装配:把爬虫结构体的信息、以及处理后的动态参数信息,装配到请求对象 req。

嵌套的比较复杂,这三部分代码可以通过 封装函数进行优化。不过目前更重要的还是发送 req 对象,尤其是以多线程的方式发送请求,需要进一步深入查看 crawlergo 的项目代码。第六步和第七步都是其他阶段的任务,可以查看下一章。

func main() {// 定义 req 对象var reqFuzz Request// 代理字段,需要等合并代码时设置相同的字段// reqFuzz.Proxy = crawler.// 1.读取爬虫结果crawlerReq := read_crawlerReq()// 2.读取参数 Fuzz 字典/*功能说明:读取得到一个数组,数组里的元素是 Payload 字典。可以通过遍历数组来逐个读取装配 Payload。调用说明:每次装配 payload 都要绑定一个 request以便使用 payload 字典的关键字等字段判断漏洞是否存在,以及探测漏洞存在后打印 payload 信息也就是说,遍历 payload 数组,是遍历的第一层*/paramsPayloadArray := read_paramsPayload()//fmt.Println(paramsPayloadArray)// 3.从爬虫结果中筛选传递动态参数的请求for _,crawler:= range crawlerReq {if crawler.Method == "GET" {if strings.Contains(crawler.Url, "?") {// 4.逐个装配payload// 获取 Url 数组urlArray := strings.Split(crawler.Url, "?")// 分离Url中的Get参数// 字符串中不包含&时,并不会报错,而是返回只有一个元素的数组paramsArray := strings.Split(urlArray[1], "&")// 装配payload:直接使用 payload 分别替换参数,比如用 id=1<script>alert(/xss/)</script> 替换 id=1for _, value := range paramsArray {// 4.遍历payload装配到每个Get参数,逐个添加 Payload 到动态参数末尾for _, payloadDict := range paramsPayloadArray.Data {payload := value + payloadDict.Payloadfmt.Println("原数据:" + value)fmt.Println("替换后的数据:" + payload)// 5.设置 req 对象,使用 payload 替换元素值,然后装配所有数据reqFuzz.URL = strings.Replace(crawler.Url, value, payload, 1)reqFuzz.Method = crawler.MethodreqFuzz.Headers = crawler.HeadersreqFuzz.PostData = crawler.Data// 6.发送 req 对象,接收响应信息// 7.根据响应信息、以及payload中的关键字、响应时间等信息验证漏洞,如果存在则打印。over}}// 保存传递动态参数的URL信息到文件:params_JsonPathoutputParamsResult(crawler)}}if crawler.Method == "POST" {// 4.逐个装配Post参数paramsArray := strings.Split(crawler.Data, "&")// 遍历每个Post参数for _, value := range paramsArray {// 4.遍历payload装配到每个Get参数,逐个添加 Payload 到动态参数末尾for _, payloadDict := range paramsPayloadArray.Data {payload := value + payloadDict.Payloadfmt.Println("原数据:" + value)fmt.Println("替换后的数据:" + payload)// 5.设置 req 对象,使用 payload 替换元素值,然后装配所有数据reqFuzz.URL = strings.Replace(crawler.Data, value, payload, 1)reqFuzz.Method = crawler.MethodreqFuzz.Headers = crawler.HeadersreqFuzz.PostData = crawler.Data// 6.发送 req 对象,接收响应信息// 7.根据响应信息、以及payload中的关键字、响应时间等信息验证漏洞,如果存在则打印。over}}outputParamsResult(crawler)}}
}

执行阶段

另开一篇文章进行记录,可以前往博客检索查看。

接收结果并验证阶段

另开一篇文章进行记录,可以前往博客检索查看。

这篇关于【毕设扫描器】【参数Fuzz】第一篇:数据的定义、读取和装配(爬虫数据和Payload数据)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!


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

相关文章

C#监听txt文档获取新数据方式

《C#监听txt文档获取新数据方式》文章介绍通过监听txt文件获取最新数据,并实现开机自启动、禁用窗口关闭按钮、阻止Ctrl+C中断及防止程序退出等功能,代码整合于主函数中,供参考学习... 目录前言一、监听txt文档增加数据二、其他功能1. 设置开机自启动2. 禁止控制台窗口关闭按钮3. 阻止Ctrl +

java如何实现高并发场景下三级缓存的数据一致性

《java如何实现高并发场景下三级缓存的数据一致性》这篇文章主要为大家详细介绍了java如何实现高并发场景下三级缓存的数据一致性,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 下面代码是一个使用Java和Redisson实现的三级缓存服务,主要功能包括:1.缓存结构:本地缓存:使

在MySQL中实现冷热数据分离的方法及使用场景底层原理解析

《在MySQL中实现冷热数据分离的方法及使用场景底层原理解析》MySQL冷热数据分离通过分表/分区策略、数据归档和索引优化,将频繁访问的热数据与冷数据分开存储,提升查询效率并降低存储成本,适用于高并发... 目录实现冷热数据分离1. 分表策略2. 使用分区表3. 数据归档与迁移在mysql中实现冷热数据分

C#解析JSON数据全攻略指南

《C#解析JSON数据全攻略指南》这篇文章主要为大家详细介绍了使用C#解析JSON数据全攻略指南,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录一、为什么jsON是C#开发必修课?二、四步搞定网络JSON数据1. 获取数据 - HttpClient最佳实践2. 动态解析 - 快速

Python使用openpyxl读取Excel的操作详解

《Python使用openpyxl读取Excel的操作详解》本文介绍了使用Python的openpyxl库进行Excel文件的创建、读写、数据操作、工作簿与工作表管理,包括创建工作簿、加载工作簿、操作... 目录1 概述1.1 图示1.2 安装第三方库2 工作簿 workbook2.1 创建:Workboo

MyBatis-Plus通用中等、大量数据分批查询和处理方法

《MyBatis-Plus通用中等、大量数据分批查询和处理方法》文章介绍MyBatis-Plus分页查询处理,通过函数式接口与Lambda表达式实现通用逻辑,方法抽象但功能强大,建议扩展分批处理及流式... 目录函数式接口获取分页数据接口数据处理接口通用逻辑工具类使用方法简单查询自定义查询方法总结函数式接口

Spring Boot spring-boot-maven-plugin 参数配置详解(最新推荐)

《SpringBootspring-boot-maven-plugin参数配置详解(最新推荐)》文章介绍了SpringBootMaven插件的5个核心目标(repackage、run、start... 目录一 spring-boot-maven-plugin 插件的5个Goals二 应用场景1 重新打包应用

Java中读取YAML文件配置信息常见问题及解决方法

《Java中读取YAML文件配置信息常见问题及解决方法》:本文主要介绍Java中读取YAML文件配置信息常见问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要... 目录1 使用Spring Boot的@ConfigurationProperties2. 使用@Valu

SQL中如何添加数据(常见方法及示例)

《SQL中如何添加数据(常见方法及示例)》SQL全称为StructuredQueryLanguage,是一种用于管理关系数据库的标准编程语言,下面给大家介绍SQL中如何添加数据,感兴趣的朋友一起看看吧... 目录在mysql中,有多种方法可以添加数据。以下是一些常见的方法及其示例。1. 使用INSERT I

Python使用vllm处理多模态数据的预处理技巧

《Python使用vllm处理多模态数据的预处理技巧》本文深入探讨了在Python环境下使用vLLM处理多模态数据的预处理技巧,我们将从基础概念出发,详细讲解文本、图像、音频等多模态数据的预处理方法,... 目录1. 背景介绍1.1 目的和范围1.2 预期读者1.3 文档结构概述1.4 术语表1.4.1 核