CTF入门必刷:HTTP协议考点全解析与curl实战通关指南
第一次在CTFHub技能树上点开Web方向最先撞见的就是Web前置技能里的HTTP协议。这组题我前后刷了三遍第一遍纯靠搜稀里糊涂过了第二遍才意识到它其实是整个Web渗透的底子——后面绕来绕去离不开的请求方法、Cookie伪造、头部字段、URL编码全都能在这一关找到原型。这篇就把我实际通关的过程、每个考点的原理还有踩过的坑一次说清楚。这组题适合刚入门CTF、对Web开发有一点基础但没系统看过HTTP协议的同学。你不需要先啃完RFC文档只要会开浏览器F12、会敲几行curl跟着思路走完就能把协议层最常用的攻击面摸个遍。与其说是解密题不如说是用考场的方式逼你把请求头和响应头逐行读明白。1. 这组题到底在考什么请求、响应与工具准备1.1 为什么HTTP协议被放到Web方向最前面Web安全本质上就是在跟HTTP协议打交道。SQL注入是改参数值XSS是构造URL文件上传是改Content-Type越权是动Cookie——这些攻击最终都落在HTTP请求的某一段上。如果不知道GET和POST的语义区别、不清楚Cookie是怎么被服务器校验的、不明白Referer和X-Forwarded-For什么时候可信那做后面的题就总隔着一层窗户纸。CTFHub把HTTP协议当成Web方向的守门关卡用意很直白先确认你会看包。这里的看包不只是打开抓包工具看流量而是看到一组请求响应就能判断出服务器信任了什么、校验了什么、忽略了什么。很多题目根本不涉及代码漏洞纯粹是利用了开发者对HTTP协议细节的误用——这种题目恰好是练协议敏感度的最佳素材。1.2 通关要用的三样工具这组题对工具的要求极低我实际用到的核心就是三个浏览器开发者工具按F12打开Network面板能看到每一个请求的完整请求头和响应头Application面板能直接改Cookie。最方便的是右键请求记录选择Copy as cURL能把浏览器请求原样转成命令行。curl后端不依赖图形界面时最稳的武器。一个请求头对应一个参数逻辑清晰方便反复试错。Burp Suite我平时习惯开着它的Repeater来改包重放效率和直观度都比浏览器高。不过说实话这组题用浏览器curl就完全够了Burp属于可选装备。我个人建议优先学会curl而不是一上来就依赖Burp。原因很简单curl的参数和HTTP协议字段是一一对应的你每写一个-H或-A就强迫自己理解了一次头部字段含义。用图形工具改包虽然快但太容易让人跳过理解这一步。2. 请求方法实战GET改POST就能拿Flag2.1 题目长什么样卡点在哪里这类题是最友好的开局。页面打开后给你一个URL默认用GET访问返回的响应提示大意为此接口需要POST请求。很多新手卡住是因为不知道浏览器地址栏只能发GET哪怕你把URL里的参数改了、按了回车它还是GET这跟刷新是一个道理。这里还藏着一个知识点看到405 Method Not Allowed基本就说明URL本身是通的只是方法不对。有些平台给的提示更委婉会在页面正文里写请使用POST方法这时候直接用curl -X POST打过去就能看到Flag出现。2.2 用curl快速切换请求方法先看一个最直接的构造方式curl -X POST http://challenge.example.com/flag-X的作用是显式声明请求方法。不过要提醒一句-X POST和-d混用时要小心因为curl遇到-d默认就会转成POST手动再加-X POST有时会在重定向场景下引起歧义。更严谨的写法是curl -d http://challenge.example.com/flag-d 表示提交一个空的POST主体效果和POST请求一致但语义更清晰。做题时两种都能过我更推荐后者因为它符合POST通常带数据体的真实场景后面做带参数的POST题时也不用改思路。2.3 拿到响应后先看完整返回别只盯着Flag第一次做这类题时我拿到Flag就急着提交结果后面出了个小问题同一道题有一步需要的线索藏在响应头里的Set-Cookie或者自定义字段中我因为没看完整响应又回头多花了几分钟。规范做法是每次请求后都用-i参数把响应头一起打出来或者干脆看完整个页面源码再走curl -i -d http://challenge.example.com/flag响应体里可能直接就是Flag也可能只有一个提示真正的信息藏在响应头中。养成每次全看的习惯后面几乎所有题目都会因此受益。3. Cookie与认证变形服务器信任的就是你的身份3.1 修改一个Cookie就能变身管理员第二种常见出法涉及Cookie典型逻辑是服务端拿到Cookie里的身份字段后直接相信不做任何签名校验。题目会给你一个普通用户的Cookie比如userguest页面返回权限不足此时把Cookie改成useradmin再访问身份就变了。这种漏洞在真实系统里经常出现在记住我功能或内部管理系统里。开发者图省事把用户名甚至用户ID直接放进Cookie并明文传递却忽略了客户端可以随意修改Cookie这个事实。Cookie不像Token那样有签名保护它就是一组由服务器发给浏览器、下次再带回来的键值对改起来没有任何门槛。操作上我习惯用开发者工具的Application面板找到左侧Storage下的Cookies项选中目标域名直接在表里把user的值改成admin然后刷新页面。也可以一步到位用curlcurl -b useradmin http://challenge.example.com/flag3.2 从Cookie到HTTP Basic Auth有的题目会给Cookie玩法加一层壳改成HTTP Basic Auth要求你通过Authorization: Basic头发送用户名密码。Basic Auth的编码规则很简单把用户名:密码用Base64编码后拼在Basic后面。注意Base64不是加密拿到字符串任何人都能还原所以它更像一个防君子不防小人的格式。自己构造的话可以用下面这串命令echo -n admin:123456 | base64 curl -H Authorization: Basic YWRtaW46MTIzNDU2 http://challenge.example.com/flag有些题目不直接给明文账号密码而是让你从响应头或者网页源码里找到一段Base64这时直接在命令行里echo xxx | base64 -d解码看内容比可视化工具快得多。记住解出明文后不一定是密码也有可能是某个token或者下一道题的URL。3.3 身份类题目的通用排查思路遇到身份验证相关的题我的排查顺序是这样的先看服务器发过来哪些Cookie再想哪个字段可能被用作身份判断然后用不同值尝试。如果Cookie没反应就观察请求头里有没有Authorization字段。如果也没有才去页面源码里找线索。这类题目真正的考点不是你会不会改包而是你能不能判断出服务器信任了什么。有时候题目故意给出一个看似随机生成的Cookie值比如sessionhackme新手会觉得无从下手但只要往Cookie管理面板里一看就会发现这个值本身是提示改完了Flag直接出现。多试几次之后你会发现大部分出题人的思路都逃不出这几个模型。4. 头部字段排查答案就写在请求和响应头上4.1 响应头里直接找Flag这一类的核心就三个字看头部。题目访问后正文只有个欢迎来到xxx看起来毫无线索但一开F12的Network面板响应头里赫然写着flag{...}或FLAG: 一串十六进制。出题人想考察的就是你会不会主动关注响应头而不仅仅是渲染出来的页面。curl里加-i就能看到完整头部也可以单独看响应头curl -I http://challenge.example.com/flag-I发的是HEAD请求只取响应头不取页面正文。不过有的服务端对HEAD请求支持不完整可能会给出奇怪结果所以更稳妥的还是-i看全量返回。4.2 特定User-Agent才能访问另一个常见变形是限制User-Agent。服务器判断你是哪个客户端最依赖的就是这个字段而它完全由客户端自己声明。题目可能要求请使用某专用浏览器访问或者直接指出只允许管理员浏览器访问这时候把UA随便改一个值就能过。用curl指定UAcurl -A Mozilla/5.0 (Windows NT 10.0; Win64; x64) AdminBrowser/1.0 http://challenge.example.com/flag有时候题目不给你具体UA字符串而是在页面源码里给你一个线索词比如UA中必须包含hacker那你就拼一个包含该关键词的UA去访问。这类题的思维是服务器对某个请求头做了检查但你永远可以伪造这个请求头因为HTTP是客户端说了算。4.3 本地访问限制与X-Forwarded-For还有一类高频题型服务器提示只允许来自本地的访问你却明明就是本机访问为什么会被拒出题人一般是用X-Forwarded-For头来判断来源IP。这个头本来是给反向代理用的用来记录客户端真实IP但很多开发者会直接信任它作为访问来源依据这就给了人伪造空间。构造方法curl -H X-Forwarded-For: 127.0.0.1 http://challenge.example.com/flag有些题里同时检查X-Real-IP或Client-IP一次性多带几个头保险curl -H X-Forwarded-For: 127.0.0.1 -H X-Real-IP: 127.0.0.1 -H Client-IP: 127.0.0.1 http://challenge.example.com/flag这个考点的现实意义非常大。很多内网管理后台就是靠检查XFF来决定是否放行的而攻击者只需要加一行头部就能绕过IP限制。理解它之后你看到只允许内网访问这类提示时第一反应就不再是猜内网IP而是直接想着伪造来源头试试。5. URL编码与双重解码小细节大坑5.1 一次URL编码和两次URL编码的区别URL编码题在CTFHub的HTTP协议关卡里很经典难度会突然上一截。它要求你对参数进行编码后提交更进阶的版本要求双重URL编码。很多新手只编了一次Flag就是不出现原因在于没有理解服务端接收参数时还会自动解码一次。URL编码的基本规则是非字母数字的字符用%加上两位十六进制表示比如空格是%20/是%2F是%26。如果要对一段文本做双重编码就得注意%本身的编码是%25。拿字符_举例单次编码后是%5F再做第二次编码时百分号会被编码成%25最终变成%255F。服务端收到后解两次第一次把%25还原成%第二次把%5F还原成_才拿到原始值。5.2 编码工具与正手操作手写编码容易出错我推荐用Python的urllib.parse它逻辑比在线工具透明还不容易受浏览器自动解码的干扰from urllib.parse import quote payload admin encode_once quote(payload) encode_twice quote(encode_once) print(encode_once) # %61%64%6D%69%6E print(encode_twice) # %2561%2564%256D%2569%256E然后把%2561%2564%256D%2569%256E放在请求参数里发给目标。这里有个经验用浏览器地址栏做双重编码测试时地址栏自己会再做一次解码导致你很难确认实际发送出去的是什么所以这种题我基本只用curl或Burp避免浏览器在中间帮倒忙。5.3 为什么要考双重编码从攻击视角看双重编码考察的是解码次数不一致的问题。某些服务端框架对URL参数先解码一遍传给业务代码业务里又有一个过滤函数对内容解码一遍如果攻击者把payload双重编码过滤函数看到的是无害字符串解码后却变成危险字符从而绕过检测。经典的路径穿越、SQL注入WAF绕过都用到过这个思路。做这道题的时候建议手算一遍从明文到双重编码的完整过程而不是直接跑脚本拿结果。我当初偷懒直接编码完就提交出了错误也不知道是编码层问题还是参数位置问题老老实实自己推一遍之后后面遇到更复杂的编码绕过题就顺多了。6. HTTP版本、状态码与综合请求构造6.1 HTTP/1.0和HTTP/1.1会用不同逻辑响应有一部分题会考察HTTP协议版本差异。同一个URL用HTTP/1.0访问返回的是一段普通页面用HTTP/1.1访问则直接泄露Flag或者反过来。原因是服务端可能根据请求版本做了不同逻辑比如旧版本通配、新版本限制。curl里切换版本curl --http1.0 http://challenge.example.com/flag curl --http1.1 http://challenge.example.com/flag把两个版本的输出对比着看差异非常直观。这个考点在真实渗透中很少直接让你拿Flag但理解版本差异有助于排查很多诡异的访问问题比如某些网关对HTTP/1.0请求不缓存、某些WAF规则只匹配特定版本等。做这题时我最大的收获是养成了版本不同结果可能完全不同的意识。6.2 状态码阅读与重定向处理状态码做题时很容易被忽略其实它本身就是线索。403表示禁止访问305/307表示重定向401表示需要认证405表示方法不允许404表示不存在。看到403时意味着你发出了请求但权限不够此时优先思考伪造头部或改变方法看到302时一定要关注Location响应头指向哪里有时候Flag就藏在重定向的目标地址里。curl默认不会跟随重定向需要加-L才会一层层跳转。所以遇到302别急着说没反应先看看响应头里的Location字段再用-L跟随一次往往直接就出来了curl -L -H X-Forwarded-For: 127.0.0.1 http://challenge.example.com/flag6.3 综合演练完整的一次通关构造如果把前面这些考点组合起来就是一道综合性很强的题要求POST方法、携带管理员Cookie、UA包含指定关键词、XFF为本机地址。初始请求长这样curl -i http://challenge.example.com/flag返回405但响应头里有个提示字段Hint: POST_And_Admin_UA_Local那就把条件全加上curl -i \ -H Cookie: useradmin \ -A Mozilla/5.0 AdminBrowser/1.0 \ -H X-Forwarded-For: 127.0.0.1 \ -d \ http://challenge.example.com/flag这种组合题的妙处在于出题人把每个线索都放在了上一层的响应中你得学会读题。做的时候逐条添加请求头每加一个就对比一次响应变化这样即使组合失败也能快速定位是哪一个条件没满足。我最开始一口气把所有头全加上报错了根本不知道是哪个条件不对后来改成逐个加、逐个验证效率反而高很多。7. 常见问题与排错心得7.1 高频翻车现场速查表下面这张表是我刷题过程中真实遇到过的翻车情况整理出来供大家对照排查现象原因解决方式改完Cookie刷新后还是普通用户Cookie的name拼写不对或值带了引号仔细对照响应里Set-Cookie的字段名用-b useradmin精确赋值用-X POST发请求但响应和GET一样服务端识别POST靠的是有没有请求体加-d 提交空数据而不是只改方法带XFF还是提示非本地访问服务端同时校验其他头或来源IP同时尝试X-Real-IP、Client-IP或把XFF设成localhostURL编码提交后还是无效只编码了一次或者被浏览器自动解码用curl或Burp提交确保双重编码后的%25被完整发送用浏览器看到Flag但curl没看到浏览器带了额外的Cookie或UA右键请求选择Copy as cURL在真实请求头上追加修改请求总被重定向到登录页缺少认证相关头或Cookie状态不对先看Location和Set-Cookie响应携带新Cookie再访问HTTP/1.1访问结果异常服务端区分协议版本返回内容切换--http1.0和--http1.1对比响应差异7.2 我踩过的几个坑希望你别踩第一个坑在开发者工具里手动改了Cookie但改完直接刷新页面而不是重新发请求结果浏览器从缓存里加载了旧响应。排查方式很简单F12 Network面板勾选Disable cache或者用curl重新请求别靠肉眼刷新判断结果。第二个坑复制粘贴响应头里的Flag时把开头或结尾的空白字符带进了提交框导致Flag一直提示错误。这种坑最无语因为肉眼根本看不出来。建议提交前先把Flag粘贴到文本编辑器里打开显示空白字符的功能检查一遍。第三个坑把Authorization头的格式写错。Basic Auth要求Basic和Base64之间有一个空格少了空格或者大小写不对都会导致认证失败。同理Cookie头里键值之间的分号和空格也要原样保留有些服务器解析很严格。7.3 通关以后怎么把协议知识用起来刷完CTFHub这组HTTP协议题不建议立刻去刷下一批题而是先把请求头字段从头到尾过一遍Accept、Accept-Encoding、Connection、Upgrade-Insecure-Requests、Sec-Fetch-*每个字段是什么语义、什么时候出现、能不能伪造都搞明白。我自己的感觉是只有这一步做完后面上手SQL注入和XSS时才会觉得攻击面是连续的。另外强烈建议把自己电脑上随便一个本地服务跑起来用curl给不同路径发不同方法、改不同头看看服务端日志里到底记录了哪些内容、忽略了哪些内容。日志会告诉你服务器真正相信什么这比任何题目都更有说服力。想深入的话也可以把RFC 9110里关于请求语义和头字段的章节翻一翻不要求全背但至少见到字段名能知道它准备干什么。就我个人体会而言HTTP协议这组题真正的价值不是那几道题的Flag而是逼你建立了一个习惯拿到一个请求包先逐个字段问一遍这个字段是否被服务端信任如果我改了它会怎样。带着这个习惯去做后面的Web题你会发现自己少了很多莫名其妙卡住的时刻。如果刷题过程中你也有什么独特的卡点欢迎分享出来方法这种东西多交流一次就多一条路。

相关新闻

游戏网关远程管理工具包:轻量内嵌HTTP服务实现多平台GM治理

游戏网关远程管理工具包:轻量内嵌HTTP服务实现多平台GM治理

简介:这是一款专为问道游戏服务端运维人员与GM(游戏管理员)设计的跨平台网页远程管理工具包,解决传统网关管理依赖本地客户端、多系统适配难、移动端无法操作等痛点,适用于Linux/Windows/macOS等环境下的服务端日常监控…

2026/10/18 19:48:32 阅读更多 →
C语言学习笔记与程序实例:从语法到内存管理的知识地图

C语言学习笔记与程序实例:从语法到内存管理的知识地图

简介:这份C语言学习资料以程序实例为主线,面向刚接触C语言的初学者以及希望巩固基础的开发者,帮助读者在动手实践中理解语法、算法与模块化编程。压缩包共8个文件,以7个cpp源码文件和1份doc学习笔记为主,源码对应基础输…

2026/10/18 19:48:32 阅读更多 →
TuriX-CUA实战:让大模型像人一样操作Windows和macOS

TuriX-CUA实战:让大模型像人一样操作Windows和macOS

1. 项目概述这阵子开源社区里冒出来个挺有意思的项目——TuriX-CUA,一个完全开源的 Computer-Use Agent(计算机使用代理)。说白了,它做的事儿就是让大模型自己“看”屏幕、“点”鼠标、“敲”键盘,像真人一样操作 Wind…

2026/10/18 19:48:32 阅读更多 →

最新新闻

720VR全景源码系统实战:从部署到二次开发全解析

720VR全景源码系统实战:从部署到二次开发全解析

简介:这是一套面向开发者与建站团队的720度VR全景网站源码系统,用于快速搭建可旋转、缩放浏览的沉浸式全景展示平台,适合需要自建全景图制作与分享站点、又不想从零开发的中高级技术人员。压缩包共1946个文件,约104.53MB&#xff…

2026/10/18 20:41:11 阅读更多 →
逻辑控制器模块选型与调试实战:从接线到故障排查一次讲透

逻辑控制器模块选型与调试实战:从接线到故障排查一次讲透

上个月在泵站项目现场,一块6240BP10811逻辑控制器模块给了我们一个“下马威”:设备上电后ERR灯常亮,通讯状态灯怎么都不闪,主控端反复扫描不到这个子站。我蹲在柜前把背板总线、通讯线序和地址拨码一件件排查下来,最后…

2026/10/18 20:41:11 阅读更多 →
Linux网络编程实战:从TCP/IP协议栈到socket与epoll

Linux网络编程实战:从TCP/IP协议栈到socket与epoll

1. 当一次网络请求发生:协议栈在Linux内核里的真实旅程很多刚接触Linux系统编程的人都会问同一个问题:我们写网络程序,到底是在和谁打交道?是那个叫"网络协议"的东西吗?更具体一点说,在浏览器里输…

2026/10/18 20:41:11 阅读更多 →
多模态统一序列建模实战:NextFlow从设计到训练解析

多模态统一序列建模实战:NextFlow从设计到训练解析

1. 从"两套模型"到一套统一序列建模:NextFlow在做什么如果你最近在公司里折腾过多模态项目,大概率也撞上过那个经典尴尬:模型 A 能把一张图说得头头是道,你问它里面有几只鸟、什么颜色、正在干什么,它都能给…

2026/10/18 20:41:11 阅读更多 →
零基础学C语言:学习笔记与程序实例带你从入门到实践

零基础学C语言:学习笔记与程序实例带你从入门到实践

简介:这份C语言学习资料以程序实例为主线,面向刚接触C语言的初学者以及希望巩固基础的开发者,帮助读者在动手实践中理解基本语法、算法、函数与文件操作等核心内容。压缩包共8个文件,以7个cpp源码文件和1份doc学习笔记为主&#x…

2026/10/18 20:41:11 阅读更多 →
深度学习驱动的网络入侵检测:从数据预处理到模型调优的完整实践指南

深度学习驱动的网络入侵检测:从数据预处理到模型调优的完整实践指南

去年我做完这个课题的时候,最大的感触就是“这个题看着不新鲜,做起来到处都是坑”。名字叫“基于深度学习的网络入侵检测模型设计与实现”,放在信息安全毕设里属于那种每年都会出现的热门题,但正因为做的人多,如果不能…

2026/10/18 20:40:10 阅读更多 →

日新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

周新闻

基于GMM的语音识别系统原理与MATLAB实现详解

基于GMM的语音识别系统原理与MATLAB实现详解

说到基于高斯混合模型(GMM)的语音识别系统,很多人第一反应就是一堆数学公式,觉得门槛很高。但如果你真的在MATLAB里把它落地跑通,会发现核心其实就是三件事:把声音变成特征向量,用GMM给每个类别…

2026/10/18 0:00:55 阅读更多 →
数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理入门:反白、灰度化、调色板修改与导出txt实践

数字图像处理这四个字听起来挺唬人,但落到具体操作上,无非就是让计算机按你的想法“摆弄”像素。我在一个模拟项目X里用了一套特别经典的基础处理流程:对图像做反白、改调色板、彩色转灰度,最后把像素数据导出成txt文件。单看每一…

2026/10/18 0:00:55 阅读更多 →
机器人大脑技术盘点:具身智能的感知、决策与数据闭环

机器人大脑技术盘点:具身智能的感知、决策与数据闭环

如果你的信息流最近也天天刷到“机器人大脑”这个词,你会发现一个很有意思的现象:每个人说的“大脑”根本不是同一个东西。有人指的是大语言模型,有人指的是运动控制系统,还有人指的是能理解物理世界的端到端模型。在2026年这个时…

2026/10/18 0:00:55 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 0:55:02 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/17 17:22:31 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/18 12:16:16 阅读更多 →