修复搜索页面会重复出现搜索框的问题;页面底部支持公安备案,取消社交图标。

This commit is contained in:
blue-cape 2025-03-21 22:40:32 +08:00
parent 0a584bafca
commit c737db897b
6 changed files with 147 additions and 353 deletions

View File

@ -1,7 +1,6 @@
---
import Hr from "./Hr.astro";
import Socials from "./Socials.astro";
import '../config'
import "../config";
import { SITE } from "../config";
const currentYear = new Date().getFullYear();
@ -15,14 +14,34 @@ const { noMarginTop = false } = Astro.props;
<footer class:list={["w-full", { "mt-auto": !noMarginTop }]}>
<Hr noPadding />
<div
class="flex flex-col items-center justify-between py-6 sm:flex-row-reverse sm:py-4"
>
<Socials centered />
<div class="my-2 flex flex-col items-center whitespace-nowrap sm:flex-row">
<div class="flex flex-col items-center py-4 sm:py-3">
<div class="flex flex-col sm:flex-row items-center gap-2 mb-2">
{SITE.gabeian.enabled && (
<div class="flex items-center gap-1">
<img src="/assets/gabeian.png" alt="Gabeian" class="h-4 w-4" />
<a
href="https://beian.mps.gov.cn/#/query/webSearch?code=41168102000247"
rel="noreferrer"
target="_blank"
class="underline hover:text-accent hover:no-underline"
>
{SITE.gabeian.id}
</a>
</div>
)}
{SITE.beian.enabled && (
<a
href="https://beian.miit.gov.cn/"
target="_blank"
class="underline hover:text-accent hover:no-underline"
>
{SITE.beian.id}
</a>
)}
</div>
<div class="flex flex-col sm:flex-row items-center whitespace-nowrap">
<span>版权所有 &#169; {SITE.created}-{currentYear}&nbsp;{SITE.author}</span>
<span class="hidden sm:inline">&nbsp;|&nbsp;</span>
<span>保留所有权利</span>
<span class="sm:ml-2">保留所有权利</span>
</div>
</div>
</footer>

View File

@ -19,5 +19,13 @@ export const SITE = {
url: "https://codeberg.org/blue-cape/astro-paper-zh/src/branch/main/src/data/blog",
text: "建议修改",
appendFilePath: true,
}
},
beian: {
enabled: false,
id: "豫ICP备2024095307号-1",
},
gabeian: {
enabled: false,
id: "豫公网安备41168102000247号",
},
} as const;

View File

@ -1,198 +0,0 @@
---
title: HTTPS代理理论及实战
pubDatetime: 2025-02-12T09:15:06+8:00
description: HTTPS代理理论及实战
slug: https-proxy
tags:
- HTTPS代理
- 中间人攻击
---
## 场景需求
| **场景** | **用途** |
|----------------|-------------------------------------------------------------------------|
| 开发调试 | 模拟 API 响应,测试客户端逻辑(如支付失败、超时场景) |
| 性能优化 | 缓存静态资源,减少重复请求网络延迟 |
| 安全测试 | 拦截敏感数据传输,检测明文泄露或弱加密问题 |
| 故障排查 | 模拟服务器 5xx 错误,验证客户端容错逻辑 |
| 隐私保护 | 通过代理隐藏真实 IP防止地理位置追踪 |
<!-- more -->
---
## HTTPS 抓包原理
### 1. HTTPS 加密的基本原理
```plaintext
HTTPS 握手流程:
1. 客户端发送 ClientHello → 协商 TLS 版本和加密套件
2. 服务端返回 ServerHello + 证书 → 身份验证
3. 客户端验证证书 → 生成预主密钥Premaster Secret
4. 服务端解密预主密钥 → 生成对称加密密钥Session Key
5. 双方使用 Session Key 加密通信
```
**关键点**
非对称加密仅用于身份验证和密钥交换,对称加密用于实际数据传输。
---
### 2. HTTPS 抓包的核心中间人攻击MITM
```mermaid
sequenceDiagram
participant Client
participant MITM_Proxy
participant Server
Client->>MITM_Proxy: 请求 HTTPS 连接ClientHello
MITM_Proxy->>Client: 返回伪造证书
Client->>MITM_Proxy: 信任证书并协商密钥
MITM_Proxy->>Server: 转发请求并建立真实 HTTPS 连接
Server->>MITM_Proxy: 返回真实加密数据
MITM_Proxy->>Client: 解密后重新加密返回
```
**必要条件**:客户端必须信任代理工具的根证书(否则浏览器会提示 `NET::ERR_CERT_AUTHORITY_INVALID`)。
---
### 3. 抓包工具的具体实现
| **工具** | **特点** |
|---------------|-------------------------------------------------------------------------|
| Fiddler | 图形化界面支持断点调试和自动化脚本FiddlerScript |
| Charles | 类似 Fiddler支持 Map Remote/Local 和 Throttling 功能 |
| mitmproxy | 命令行工具,适合自动化场景,支持 Python 脚本扩展 |
| Wireshark | 底层抓包,需配合 SSLKEYLOGFILE 解密流量 |
---
### 4. 突破 HTTPS 抓包的限制
#### 场景 1证书绑定Certificate Pinning
- **原理**:应用内置服务器证书指纹,拒绝信任系统证书。
- **绕过方案**
```bash
# Android 使用 Frida 绕过(需 root
frida -U -f com.example.app -l bypass_ssl_pinning.js
```
#### 场景 2HTTP/2 或 HTTP/3
- **对策**:确保代理工具支持最新协议(如 mitmproxy 7.0+ 支持 HTTP/2
#### 场景 3客户端检测代理
- **透明代理方案**
```bash
# Linux 使用 iptables 重定向流量
iptables -t nat -A OUTPUT -p tcp --dport 443 -j REDIRECT --to-port 8080
```
---
## 实战mitmproxy 使用指南
### 1. 安装与启动
```bash
# 安装(推荐 Python 虚拟环境)
pip install mitmproxy
# 启动交互式界面
mitmproxy -p 8080 --ssl-insecure
# 启动 Web 界面http://localhost:8081
mitmweb
```
---
### 2. 代理配置
| **客户端类型** | **配置方法** |
|---------------|-----------------------------------------------------------------------------|
| 浏览器 | 设置 → 网络设置 → 手动代理:`127.0.0.1:8080` |
| Android | Wi-Fi → 修改网络 → 高级选项 → 代理手动 → 输入主机和端口 |
| iOS | Wi-Fi → HTTP 代理 → 配置代理 → 手动 |
| 命令行工具 | 使用环境变量:<br>`export http_proxy=http://127.0.0.1:8080 https_proxy=http://127.0.0.1:8080` |
---
### 3. 证书安装
| **系统** | **操作步骤** |
|--------------|-----------------------------------------------------------------------------|
| Windows | 访问 `http://mitm.it` → 下载证书 → 双击安装到“受信任的根证书颁发机构” |
| macOS | 下载证书 → 钥匙串访问 → 添加证书 → 设置为“始终信任” |
| Android | 访问 `http://mitm.it` → 下载证书 → 设置 → 安全 → 加密与凭据 → 安装证书 |
| iOS | 访问 `http://mitm.it` → 下载描述文件 → 设置 → 已下载描述文件 → 安装 |
---
### 4. 基础操作
| **快捷键** | **功能** |
|-------------|-------------------------------------------------------------------------|
| `↑/↓` | 选择请求 |
| `Enter` | 查看请求/响应详情 |
| `Tab` | 切换请求/响应标签页 |
| `/` | 过滤请求(如 `~u example.com` 过滤 URL |
| `w` | 保存会话到文件(`.mitm` 格式) |
---
### 5. 高级功能
#### 脚本示例:修改请求头
```python
# modify_headers.py
from mitmproxy import http
def request(flow: http.HTTPFlow):
flow.request.headers["X-Debug"] = "true"
```
#### 脚本示例:模拟 API 响应
```python
# mock_api.py
from mitmproxy import http
def request(flow: http.HTTPFlow):
if "api.example.com/data" in flow.request.url:
flow.response = http.Response.make(
200,
b'{"status": "success", "data": "mocked"}',
{"Content-Type": "application/json"}
)
```
**启动命令**
```bash
mitmproxy -s modify_headers.py -s mock_api.py
```
---
### 6. 调试技巧
- **实时日志**:通过 `mitmdump -v` 查看详细日志。
- **过滤噪声**:使用 `-I` 参数忽略指定域名:
```bash
mitmproxy -I ".*google.*"
```
- **性能分析**:按 `m` 标记请求,按 `M` 查看统计信息(如响应时间分布)。
---
## 附录
### 工具对比
| **功能** | mitmproxy | Fiddler | Charles |
|------------------|-----------|---------|---------|
| 跨平台支持 | ✔️ | ❌ (Windows) | ✔️ |
| 脚本扩展 | ✔️ (Python) | ✔️ (C#) | ❌ |
| 图形化界面 | ❌ (mitmweb 基础) | ✔️ | ✔️ |
| 协议支持 | HTTP/1.1, HTTP/2 | HTTP/1.1 | HTTP/1.1, HTTP/2 |
### 常见问题
**Q1手机无法安装证书**
- 确保已关闭“证书透明性”监控iOS 设置 → Safari → 高级)。
- Android 7+ 需将证书安装到系统级(需 root
**Q2抓包时出现 `TLS handshake failed`**
- 使用 `--ssl-insecure` 参数忽略证书错误。
- 检查客户端是否信任 mitmproxy 的根证书。

View File

@ -1,47 +0,0 @@
---
title: 《七律·和郭沫若同志》——毛泽东
pubDatetime: 2025-03-08T20:00:00+08:00
description: 毛泽东通过神话重构,将革命话语融入传统叙事,展现独特的政治诗学风格。
slug: 七律-和郭沫若同志
tags:
- 诗歌
---
## 原文
**《七律·和郭沫若同志》**
一从大地起风雷,便有精生白骨堆。
僧是愚氓犹可训,妖为鬼蜮必成灾。
金猴奋起千钧棒,玉宇澄清万里埃。
今日欢呼孙大圣,只缘妖雾又重来。
## 赏析
### 1. 历史背景与政治隐喻
此诗作于1961年是对郭沫若《看〈孙悟空三打白骨精〉》一诗的和作。时值国际共产主义运动分歧加剧中苏论战国内处于经济困难时期。毛泽东借《西游记》中孙悟空三打白骨精的典故以寓言形式表达对阶级斗争的深刻思考。
**意象解析:**
**"白骨堆"**:象征腐朽落后的反动势力,暗指国际修正主义及国内敌对力量。
**"僧"(唐僧)**:指代思想动摇但可争取的中间派,体现"团结—批评—团结"策略。
**"妖"(白骨精)**:喻指不可调和的阶级敌人,强调其破坏性本质。
**"金猴"(孙悟空)**:无产阶级革命力量的化身,"千钧棒"象征革命武装斗争。
---
### 2. 艺术特色
**革命浪漫主义**:将神话意象与政治现实结合,如"玉宇澄清"展现理想社会图景。
**对比手法**:通过"僧"与"妖"的对比,强化敌我矛盾的不可调和性。
**用典创新**:颠覆传统对唐僧的同情式解读,体现阶级分析视角。
---
### 3. 哲学内涵
尾联"妖雾又重来"揭示斗争长期性,呼应"阶级斗争要年年讲,月月讲"的政治理念。诗中体现的"矛盾斗争推动历史发展"思想,是其辩证法哲学的诗意表达。
## 思想价值
该诗以文艺形式阐述政治主张,体现毛泽东"古为今用"的文艺观。其核心思想——在复杂斗争中保持革命警惕性,对当代仍具启示意义。

View File

@ -107,5 +107,3 @@ tags:
30. [ ] 《命运之门》
31. [ ] 《灯火阑珊》
32. [ ] 《阿加莎·克里斯蒂自传》历时15年完成
---

View File

@ -18,115 +18,129 @@ const backUrl = SITE.showBackButton ? `${Astro.url.pathname}` : "/";
</Layout>
<script>
function initSearch() {
const pageFindSearch: HTMLElement | null =
document.querySelector("#pagefind-search");
let searchInstance: any = null;
if (!pageFindSearch) return;
function initSearch() {
const pageFindSearch: HTMLElement | null =
document.querySelector("#pagefind-search");
const params = new URLSearchParams(window.location.search);
if (!pageFindSearch) return;
if (searchInstance) return;
const onIdle = window.requestIdleCallback || (cb => setTimeout(cb, 1));
const params = new URLSearchParams(window.location.search);
onIdle(async () => {
// @ts-expect-error — Missing types for @pagefind/default-ui package.
const { PagefindUI } = await import("@pagefind/default-ui");
const onIdle = window.requestIdleCallback || (cb => setTimeout(cb, 1));
// Display warning inn dev mode
if (import.meta.env.DEV) {
pageFindSearch.innerHTML = `
<div class="bg-muted/75 rounded p-4 space-y-4 mb-4">
<p><strong>开发模式警告!</strong>在开发期间,您需要至少构建一次项目才能看到搜索结果。</p>
<code class="block bg-black text-white px-2 py-1 rounded">pnpm run build</code>
</div>
`;
}
onIdle(async () => {
// @ts-expect-error — Missing types for @pagefind/default-ui package.
const { PagefindUI } = await import("@pagefind/default-ui");
// Init pagefind ui
const search = new PagefindUI({
element: "#pagefind-search",
showSubResults: true,
showImages: false,
processTerm: function (term: string) {
params.set("q", term); // Update the `q` parameter in the URL
history.replaceState(history.state, "", "?" + params.toString()); // Push the new URL without reloading
// Display warning inn dev mode
if (import.meta.env.DEV) {
pageFindSearch.innerHTML = `
<div class="bg-muted/75 rounded p-4 space-y-4 mb-4">
<p><strong>开发模式警告!</strong>在开发期间,您需要至少构建一次项目才能看到搜索结果。</p>
<code class="block bg-black text-white px-2 py-1 rounded">pnpm run build</code>
</div>
`;
}
const backUrl = pageFindSearch?.dataset?.backurl;
sessionStorage.setItem("backUrl", backUrl + "?" + params.toString());
// Init pagefind ui
searchInstance = new PagefindUI({
element: "#pagefind-search",
showSubResults: true,
showImages: false,
processTerm: function (term: string) {
params.set("q", term); // Update the `q` parameter in the URL
history.replaceState(history.state, "", "?" + params.toString()); // Push the new URL without reloading
return term;
},
});
const backUrl = pageFindSearch?.dataset?.backurl;
sessionStorage.setItem("backUrl", backUrl + "?" + params.toString());
// If search param exists (eg: search?q=astro), trigger search
const query = params.get("q");
if (query) {
search.triggerSearch(query);
}
// Reset search param if search input is cleared
const searchInput = document.querySelector(".pagefind-ui__search-input");
const clearButton = document.querySelector(".pagefind-ui__search-clear");
searchInput?.addEventListener("input", resetSearchParam);
clearButton?.addEventListener("click", resetSearchParam);
function resetSearchParam(e: Event) {
if ((e.target as HTMLInputElement)?.value.trim() === "") {
history.replaceState(history.state, "", window.location.pathname);
}
}
return term;
},
});
}
document.addEventListener("astro:after-swap", initSearch);
initSearch();
// If search param exists (eg: search?q=astro), trigger search
const query = params.get("q");
if (query) {
searchInstance.triggerSearch(query);
}
// Reset search param if search input is cleared
const searchInput = document.querySelector(".pagefind-ui__search-input");
const clearButton = document.querySelector(".pagefind-ui__search-clear");
searchInput?.addEventListener("input", resetSearchParam);
clearButton?.addEventListener("click", resetSearchParam);
function resetSearchParam(e: Event) {
if ((e.target as HTMLInputElement)?.value.trim() === "") {
history.replaceState(history.state, "", window.location.pathname);
}
}
});
}
function cleanupSearch() {
if (searchInstance) {
searchInstance = null;
const pageFindSearch = document.querySelector("#pagefind-search");
if (pageFindSearch) {
pageFindSearch.innerHTML = "";
}
}
}
document.addEventListener("astro:before-swap", cleanupSearch);
document.addEventListener("astro:after-swap", initSearch);
initSearch();
</script>
<style is:global>
#pagefind-search {
--pagefind-ui-font: var(--font-mono);
--pagefind-ui-text: var(--foreground);
--pagefind-ui-background: var(--background);
--pagefind-ui-border: var(--border);
--pagefind-ui-primary: var(--accent);
--pagefind-ui-tag: var(--background);
--pagefind-ui-border-radius: 0.375rem;
--pagefind-ui-border-width: 1px;
--pagefind-ui-image-border-radius: 8px;
--pagefind-ui-image-box-ratio: 3 / 2;
#pagefind-search {
--pagefind-ui-font: var(--font-mono);
--pagefind-ui-text: var(--foreground);
--pagefind-ui-background: var(--background);
--pagefind-ui-border: var(--border);
--pagefind-ui-primary: var(--accent);
--pagefind-ui-tag: var(--background);
--pagefind-ui-border-radius: 0.375rem;
--pagefind-ui-border-width: 1px;
--pagefind-ui-image-border-radius: 8px;
--pagefind-ui-image-box-ratio: 3 / 2;
form::before {
background-color: var(--foreground);
}
input {
font-weight: 400;
border: 1px solid var(--border);
}
input:focus-visible {
outline: 1px solid var(--accent);
}
.pagefind-ui__result-title a {
color: var(--accent);
outline-offset: 1px;
outline-color: var(--accent);
}
.pagefind-ui__result-title a:focus-visible,
.pagefind-ui__search-clear:focus-visible {
text-decoration-line: none;
outline-width: 2px;
outline-style: dashed;
}
.pagefind-ui__result:last-of-type {
border-bottom: 0;
}
.pagefind-ui__result-nested .pagefind-ui__result-link:before {
font-family: system-ui;
}
form::before {
background-color: var(--foreground);
}
</style>
input {
font-weight: 400;
border: 1px solid var(--border);
}
input:focus-visible {
outline: 1px solid var(--accent);
}
.pagefind-ui__result-title a {
color: var(--accent);
outline-offset: 1px;
outline-color: var(--accent);
}
.pagefind-ui__result-title a:focus-visible,
.pagefind-ui__search-clear:focus-visible {
text-decoration-line: none;
outline-width: 2px;
outline-style: dashed;
}
.pagefind-ui__result:last-of-type {
border-bottom: 0;
}
.pagefind-ui__result-nested .pagefind-ui__result-link:before {
font-family: system-ui;
}
}
</style>