依据 SECURITY_SEO_AUDIT.md 实施第一轮安全/SEO/GEO 修复

代码改动:
- SEO-02 产品页标题品牌重复:Product::seoTitle() 去掉品牌后缀,由视图统一追加 $siteName
- SEO-05/Geo-03 结构化数据:布局增 WebSite+SearchAction;产品页 Product+BreadcrumbList;文章页 Article+BreadcrumbList(含作者/发布日期)
- SEO-06 hreflang 自引用(zh-CN/x-default)
- SEC-02 新增 public/.well-known/security.txt
- GEO-05 新增 public/llms.txt

记录文档(供未来开发者接手):
- CHANGELOG.md:版本与变更日志
- docs/SECURITY_SEO_REMEDIATION.md:逐项状态总表 + 改动位置 + 上线 curl 自检清单
(SEC-01/REL-01~03/PHY-01~04 等需 Tailwind 构建或云端操作项标记为待办,未自动改以免破坏站点)
This commit is contained in:
2026-08-08 23:19:35 +08:00
parent f9f26ef1cc
commit 63431dd77c
8 changed files with 267 additions and 1 deletions
+46
View File
@@ -0,0 +1,46 @@
# Changelog
本文件记录 cloud-chip.cn 的版本与重要变更,供**接手维护的开发者**快速了解「改了什么、为什么、怎么验证」。
格式参考 [Keep a Changelog](https://keepachangelog.com/);版本号采用语义化版本(SemVer)。
> **源头审计**:IMA 知识库「网站测试」→ `SECURITY_SEO_AUDIT.md`
> (线上扫描 2026-08-06,对象 https://cloud-chip.cnIP 47.107.30.116 / Alibaba Cloud / nginx)。
> 每一项 IDSEC-/REL-/PHY-/SEO-/GEO-)均对应审计报告原编号。
---
## [1.0.0] - 2026-08-08
依据 `SECURITY_SEO_AUDIT.md` 实施第一轮「安全 / SEO / GEO」修复。
### Added(新增)
- `public/.well-known/security.txt`:白帽漏洞报送入口(SEC-02)。
- `public/llms.txt`:AI 引擎抓取指引(GEO-05)。
- 结构化数据:布局新增 `WebSite` + `SearchAction`;产品页 `Product` + `BreadcrumbList`;文章页 `Article` + `BreadcrumbList`SEO-05 / GEO-03)。
- 布局 `<head>` 新增 `hreflang` 自引用(`zh-CN` / `x-default`)(SEO-06)。
### Changed(修改)
- `app/Models/Product.php``seoTitle()` 不再拼接品牌后缀,改由视图统一 ` - $siteName` 追加一次,消除产品页标题品牌重复(SEO-02)。
- `resources/views/layouts/app.blade.php`:扩展 JSON-LDOrganization + WebSite)、加 hreflang。
- `resources/views/products/show.blade.php`:追加 Product + BreadcrumbList 结构化数据。
- `resources/views/articles/show.blade.php`:追加 Article + BreadcrumbList 结构化数据。
### Verified(已核验,无需改代码)
- `SEC-04`:本地 `.env``APP_DEBUG=false` / `APP_ENV=production` / `SESSION_SECURE_COOKIE=true`(上线红线;**需确认生产服务器 `.env` 与此一致**)。
- `SEO-01`:除 Hero 轮播富文本外,全站区块已用 `<h2>`;首页 `<h1>` 数量取决于 Hero 后台配置(见下「Deferred」)。
### Deferred(待办 / 需人工或云端处理,未自动改以免破坏站点)
完整清单、每项状态与验证命令见 **`docs/SECURITY_SEO_REMEDIATION.md`**。摘要:
- `SEC-01` / `REL-03`CSP 仍含 `unsafe-inline`(兼容 Tailwind Play CDN);需将 Tailwind 改为构建产物并加 nonce 后方可移除 → 较大重构,单独排期。
- `REL-02`:公开页缓存当前全局 `no-store`(避免 CSRF 419,因每页含表单 token),不可盲目放开;建议经 CDN 边缘缓存实现。
- `REL-01` / `PHY-01~04`CDN/WAF、DDoS、多实例/SLB、备份演练、健康探活 → 云端操作,不在代码库范围。
- `SEC-03``composer audit` 命令在本机 composer 版本不支持;需升级 composer 或 CI 中巡检依赖 CVE。
- `SEO-03` / `SEO-04`:品牌命名三处不一致、首页 title 堆砌,源于后台「站点设置」的 `site_name` / `seo_title_default`,需在后台改为规范名(无「官网」后缀)与自然表述。
- `GEO-01~04` / `SEO-07~08`:FAQ/HowTo 结构化数据、品牌 sameAs、作者信号(已随 Article schema 部分覆盖)、图片 alt、内链锚文本 → 内容侧持续完善。
---
## 如何阅读本报告
1. 先看 `docs/SECURITY_SEO_REMEDIATION.md` 的「状态总表」确认每项当前进度。
2. 上线后用该文档末尾的 `curl` 自检清单逐条验证。
3. 接手下一轮修复时,在本文档新增一个 `## [x.y.z]` 小节,并在 remediation 文档勾选对应项。
+3 -1
View File
@@ -42,7 +42,9 @@ class Product extends Model
public function seoTitle(): string
{
return $this->seo_title ?: ($this->name . ' - 深圳市云创芯电子有限公司');
// 仅返回实体名;品牌后缀由视图统一以 ' - ' . $siteName 追加(products/show.blade.php:4),
// 避免 Product::seoTitle() 与视图双重拼接导致标题品牌重复(审计 SEO-02)。
return $this->seo_title ?: $this->name;
}
public function seoDescription(): string
+124
View File
@@ -0,0 +1,124 @@
# 安全 / SEO / GEO 修复跟踪(SECURITY_SEO_AUDIT 落地记录)
> 配套审计报告:IMA 知识库「网站测试」→ `SECURITY_SEO_AUDIT.md`(扫描 2026-08-06,对象 https://cloud-chip.cn)。
> 本文件记录每一项审计发现的处理状态、具体改动与验证方式,**供未来接手的不同开发者直接使用**。
> 版本日志见根目录 `CHANGELOG.md`。
图例:**✅ 已落地(代码)** · **✔ 已核验(无需改)** · **⏳ 待人工(后台/数据)** · **🚫 工具限制** · **🔧 需云端/架构**
---
## 状态总表
| ID | 优先级 | 发现 | 状态 | 处理 / 改动位置 |
|---|---|---|---|---|
| SEC-01 | P0 | CSP 含 `unsafe-inline` | 🔧 需架构 | 兼容 Tailwind Play CDN;须先完成 REL-03(构建 Tailwind + nonce)再移除,属重构,未动 |
| SEC-02 | P1 | 无 security.txt | ✅ 已落地 | 新增 `public/.well-known/security.txt`(白帽报送入口) |
| SEC-03 | P1 | 依赖 CVE 未知 | 🚫 工具限制 | 本机 composer 不支持 `audit` 命令;需升级 composer 或在 CI 跑 `composer audit` / `composer outdated` |
| SEC-04 | P1 | 生产 APP_DEBUG 未核实 | ✔ 已核验 | 本地 `.env``APP_DEBUG=false` / `APP_ENV=production` / `SESSION_SECURE_COOKIE=true`;需确认生产 `.env` 一致 |
| SEC-05 | P2 | 上传未做魔数校验 | ⏳ 待人工 | 现有 `image` + `mimes:jpg,jpeg,png,gif,webp` + `max:5120` 已具备;魔数校验可后续加 `Intervention` / `finfo` |
| SEC-06 | P2 | UGC 净化一致性 | ✔ 已具备 | `config/purifier.php` 双档(default / article);论坛/页脚走 `Purifier::clean($html,'article')` |
| REL-01 | P0 | 单源站无 CDN/WAF | 🔧 需云端 | 接入阿里云 CDN/Cloudflare;静态走 CDN、动态回源(运维操作) |
| REL-02 | P0 | 公开页 `no-store` | 🔧 需架构 | 当前全局 `no-store` 为避免 CSRF 419(每页含表单 token);建议经 CDN 边缘缓存(忽略 query + ESI)实现,未盲目放开 |
| REL-03 | P1 | 强依赖外部 Tailwind CDN | 🔧 需架构 | 改为构建期编译 Tailwind → `public/css/app.css`;同时解决 SEC-01;属重构,单独排期 |
| REL-04 | P1 | 500 页是否暴露堆栈 | ✔ 已核验 | `APP_DEBUG=false` 即不泄露;可补 `resources/views/errors/500.blade.php`(可选) |
| REL-05 | P2 | OpCache / 整页缓存 | 🔧 需云端 | 开 PHP OpCache;首页/栏目页短时长整页缓存(Redis/文件),运维+代码配合 |
| REL-06 | P2 | 大图未压缩/WebP | ⏳ 待人工 | 图片转 WebP、启用 gzip/brotli(运维+上传流程) |
| PHY-01 | P0 | 无边缘 DDoS/WAF | 🔧 需云端 | 上阿里云 DDoS 防护 + WAF(运维操作) |
| PHY-02 | P0 | 单 ECS 单点 | 🔧 需云端 | 定期快照 + 多实例 + SLB;数据库独立 RDS 并自动备份(运维操作) |
| PHY-03 | P1 | 备份未验证 | 🔧 需云端 | ECS 快照 + 库异地备份 + 恢复演练,保留 ≥30 天,记 RPO/RTO(运维操作) |
| PHY-04 | P2 | 无健康探活 | 🔧 需云端 | 云监控 + supervisor 守护 + 异常自动重启(运维操作) |
| SEO-01 | P0 | 首页 3 个 `<h1>` | ✔ 已核验(代码) | 全站区块已用 `<h2>`;首页 `<h1>` 来自 Hero 轮播富文本(DB),多屏则多 `<h1>`,属后台编辑规范(见下) |
| SEO-02 | P0 | 产品页标题品牌重复 | ✅ 已落地 | `app/Models/Product.php::seoTitle()` 去掉品牌后缀,视图统一 ` - $siteName` |
| SEO-03 | P0 | 品牌命名三处不一致 | ⏳ 待人工(后台) | 代码默认 `site_name=深圳市云创芯电子有限公司` 已规范;线上「云创芯电子(你身边的PD顾问)」/「官网」后缀来自后台 `site_name`/`seo_title_default`,需改规范名 |
| SEO-04 | P1 | 首页 title 堆砌 | ⏳ 待人工(后台) | 代码默认 `seo_title_default=深圳市云创芯电子有限公司 - 多口 TypeC 接口IC` 已自然;线上堆砌版来自后台设置,需改自然表述 |
| SEO-05 | P1 | JSON-LD 仅 Organization | ✅ 已落地 | 布局加 `WebSite`+`SearchAction`;产品页 `Product`+`BreadcrumbList`;文章页 `Article`+`BreadcrumbList` |
| SEO-06 | P1 | 无 hreflang | ✅ 已落地 | 布局加 `alternate` 自引用(zh-CN / x-default |
| SEO-07 | P2 | 图片 alt 未审计 | ⏳ 待人工 | 产品/方案配图补 alt(含关键词但自然),内容侧完善 |
| SEO-08 | P2 | 内链深度/锚文本 | ⏳ 待人工 | 重要页 ≤3 次点击可达 + 描述性锚文本,内容侧完善 |
| GEO-01 | P1 | 缺 FAQ/HowTo 结构化数据 | ⏳ 待人工 | 文章/产品页加 FAQPage/HowTo schema,内容侧完善 |
| GEO-02 | P1 | 品牌实体歧义 | ⏳ 待人工 | 同 SEO-03Organization 的 `sameAs` 可指向官方主页/认证平台(代码可加,见备注) |
| GEO-03 | P2 | 缺作者/权威信号 | ✅ 已落地(部分) | 文章页 `Article` schema 已含 author/publisher/datePublished/dateModified |
| GEO-04 | P2 | 内容未直接作答 | ⏳ 待人工 | 术语/文章开头用 1–2 句直给定义,内容侧完善 |
| GEO-05 | P2 | 无 llms.txt | ✅ 已落地 | 新增 `public/llms.txt` |
| GEO-06 | P2 | 单语言限制 | ⏳ 待人工 | 同 SEO-06,英文版可扩展 AI 答案触达(需 URL 化多语言) |
---
## 已落地改动清单(代码)
1. **SEO-02**`app/Models/Product.php`
```php
public function seoTitle(): string
{
return $this->seo_title ?: $this->name; // 仅实体名;品牌由视图统一追加
}
```
视图 `resources/views/products/show.blade.php:4``@section('title', $product->seoTitle() . ' - ' . $siteName)`
2. **SEO-05 / GEO-03** — 结构化数据
- `resources/views/layouts/app.blade.php`Organization 之后新增 `WebSite` + `SearchAction`(站内搜索 `url('/search')?q={search_term_string}`)。
- `resources/views/products/show.blade.php`:追加 `Product` + `BreadcrumbList`name/description/brand/url/category)。
- `resources/views/articles/show.blade.php`:追加 `Article` + `BreadcrumbList`headline/author/publisher/datePublished/dateModified/mainEntityOfPage)。
- 均用 `json_encode(..., JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG)` 防 XSS 与 `</script>` 截断。
3. **SEO-06** — `resources/views/layouts/app.blade.php` `<head>`
```html
<link rel="alternate" hreflang="zh-CN" href="{{ url()->current() }}">
<link rel="alternate" hreflang="x-default" href="{{ url('/') }}">
```
4. **SEC-02** — `public/.well-known/security.txt`Contact / Expires / Preferred-Languages / Policy)。
5. **GEO-05** — `public/llms.txt`(站点说明 + 允许抓取栏目)。
---
## 待人工处理(后台 / 数据,非代码)
- **SEO-01(首页多 `<h1>`)**:登录后台「外观 → 首页轮播」,编辑各屏富文本时**只用 `<h2>` 作为屏内标题,全站仅首屏一个 `<h1>`**(或在富文本里不用 h1,由 Hero 文案样式承担视觉层级)。多屏都写 h1 会触发多个 h1。
- **SEO-03(品牌名)**:后台「站点设置」将 `site_name` 改为 **`深圳市云创芯电子有限公司`**(对外简称可用 `云创芯电子`,但全站统一);`seo_title_default` 去掉「官网」后缀。
- **SEO-04(首页 title**:后台「站点设置」将 `seo_title_default` 改为自然表述,例如 `云创芯电子 - 多口 TypeC 接口IC 与快充方案`,去除「PD 接口顾问 拓展坞 视频扩展 端口扩展」式堆砌。
- **GEO-02sameAs**:如需强化实体,可在 `layouts/app.blade.php` 的 Organization JSON-LD 增加 `"sameAs": ["https://..."]` 指向官方认证平台。
- **SEC-05 / REL-06 / SEO-07 / SEO-08 / GEO-01 / GEO-04**:内容/上传流程侧持续完善。
---
## 上线自检(curl 清单)
```bash
# 安全头(应含 CSP / X-Frame-Options / nosniff / Referrer-Policy / HSTS
curl -sS -I https://cloud-chip.cn/ | grep -iE 'content-security-policy|x-frame|x-content|strict-transport|referrer'
# security.txt 可达
curl -sS -o /dev/null -w 'security.txt=%{http_code}\n' https://cloud-chip.cn/.well-known/security.txt
# llms.txt 可达
curl -sS -o /dev/null -w 'llms.txt=%{http_code}\n' https://cloud-chip.cn/llms.txt
# 产品页标题不应再重复品牌
curl -sS https://cloud-chip.cn/products/cc-pd3168 | grep -iE '<title>'
# 首页 h1 数量(应为 1;若 >1 回到后台改 Hero 富文本)
curl -sS https://cloud-chip.cn/ | grep -c '<h1'
# JSON-LD 含 WebSite / Product / Article
curl -sS https://cloud-chip.cn/ | grep -c 'WebSite'
curl -sS https://cloud-chip.cn/products/cc-pd3168 | grep -c '"@type":"Product"'
curl -sS https://cloud-chip.cn/articles/<某slug> | grep -c '"@type":"Article"'
# hreflang 自引用
curl -sS https://cloud-chip.cn/ | grep -iE 'hreflang'
# sitemap 完整性(应 49 条 <loc>
curl -sS https://cloud-chip.cn/sitemap.xml | grep -c '<loc>'
# 敏感路径不应暴露
for p in /.env /phpinfo.php; do echo "$p -> $(curl -sS -o /dev/null -w '%{http_code}' https://cloud-chip.cn$p)"; done
```
---
## 备注
- 本文件与 `CHANGELOG.md` 需随代码一起提交,确保后续开发者在仓库内即可看到。
- 状态符号会随修复推进更新;请勿删除「Deferred / 待人工」项,它们是对未来开发者的明确待办。
+6
View File
@@ -0,0 +1,6 @@
Contact: mailto:security@51chip.net
Expires: 2027-08-08T00:00:00Z
Preferred-Languages: zh, en
Canonical: https://cloud-chip.cn/.well-known/security.txt
Policy: 欢迎安全研究者按负责任披露原则报送漏洞。请通过上方安全联系邮箱报送,并尽量提供复现步骤与影响评估;我们承诺在 7 个工作日内确认并跟进修复,不追究善意报送者的法律责任。
Acknowledgements: https://cloud-chip.cn/
+15
View File
@@ -0,0 +1,15 @@
# cloud-chip.cn
> 深圳市云创芯电子有限公司官方站点,专注多口 TypeC 接口 IC、PD/PHY 控制芯片与快充参考设计,面向充电与外设厂商提供选型、协议转换与同步整流控制技术支持。
## 允许 AI 引擎抓取的栏目
- 产品中心: https://cloud-chip.cn/products
- 技术文章: https://cloud-chip.cn/articles
- 解决方案: https://cloud-chip.cn/solutions
- 术语库: https://cloud-chip.cn/glossary
- 新闻动态: https://cloud-chip.cn/news
## 站点说明
- 内容语言:中文(简体)。
- 目标读者:嵌入式 / 电源工程师、采购与选型人员。
- 如需英文版、结构化数据或商务合作,请联系 service@51chip.net。
+31
View File
@@ -48,6 +48,37 @@
@endif
</article>
@php
// 结构化数据:Article + BreadcrumbList(审计 SEO-05 / GEO-03 作者与发布信号)
$logoUrl = '/images/logo-dark.png';
$articleSchema = [
'@context' => 'https://schema.org',
'@type' => 'Article',
'headline' => $article->title,
'description' => $article->seoDescription(),
'author' => ['@type' => 'Organization', 'name' => $siteName],
'publisher' => [
'@type' => 'Organization',
'name' => $siteName,
'logo' => ['@type' => 'ImageObject', 'url' => asset($logoUrl)],
],
'datePublished' => $article->published_at?->toIso8601String(),
'dateModified' => $article->updated_at?->toIso8601String(),
'mainEntityOfPage' => ['@type' => 'WebPage', '@id' => url()->current()],
];
$breadcrumbSchema = [
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => [
['@type' => 'ListItem', 'position' => 1, 'name' => '首页', 'item' => url('/')],
['@type' => 'ListItem', 'position' => 2, 'name' => '技术文章', 'item' => route('articles.index')],
['@type' => 'ListItem', 'position' => 3, 'name' => $article->title, 'item' => url()->current()],
],
];
@endphp
<script type="application/ld+json">{!! json_encode($articleSchema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG) !!}</script>
<script type="application/ld+json">{!! json_encode($breadcrumbSchema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG) !!}</script>
<div class="mt-6">
<a href="{{ route('articles.index') }}" class="inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:text-primary-hover">
<x-icon name="arrow" :size="16" class="rotate-180" /> 返回文章列表
+18
View File
@@ -27,6 +27,8 @@
<title>@yield('title', $seoTitleDefault)</title>
<meta name="description" content="@yield('description', $seoDescDefault)">
<link rel="canonical" href="{{ url()->current() }}">
<link rel="alternate" hreflang="zh-CN" href="{{ url()->current() }}">
<link rel="alternate" hreflang="x-default" href="{{ url('/') }}">
<meta property="og:type" content="website">
<meta property="og:site_name" content="{{ $siteName }}">
<meta property="og:title" content="@yield('title', $seoTitleDefault)">
@@ -107,6 +109,22 @@
"description": {!! json_encode($seoDescDefault, JSON_UNESCAPED_UNICODE) !!}
}
</script>
<script type="application/ld+json">
{
"@@context": "https://schema.org",
"@@type": "WebSite",
"name": {!! json_encode($siteName, JSON_UNESCAPED_UNICODE) !!},
"url": {!! json_encode(url('/'), JSON_UNESCAPED_UNICODE) !!},
"potentialAction": {
"@@type": "SearchAction",
"target": {
"@@type": "EntryPoint",
"urlTemplate": {!! json_encode(url('/search') . '?q={search_term_string}', JSON_UNESCAPED_UNICODE) !!}
},
"query-input": "required name=search_term_string"
}
}
</script>
</head>
<body class="font-sans text-fg bg-surface antialiased">
+24
View File
@@ -35,6 +35,30 @@
@endif
</article>
@php
// 结构化数据:Product + BreadcrumbList(审计 SEO-05
$productSchema = [
'@context' => 'https://schema.org',
'@type' => 'Product',
'name' => $product->name,
'description' => $product->seoDescription(),
'brand' => ['@type' => 'Brand', 'name' => $siteName],
'url' => url()->current(),
'category' => $product->category?->name,
];
$breadcrumbSchema = [
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => [
['@type' => 'ListItem', 'position' => 1, 'name' => '首页', 'item' => url('/')],
['@type' => 'ListItem', 'position' => 2, 'name' => '产品中心', 'item' => route('products.index')],
['@type' => 'ListItem', 'position' => 3, 'name' => $product->name, 'item' => url()->current()],
],
];
@endphp
<script type="application/ld+json">{!! json_encode($productSchema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG) !!}</script>
<script type="application/ld+json">{!! json_encode($breadcrumbSchema, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_HEX_TAG) !!}</script>
<div class="mt-6">
<a href="{{ route('products.index') }}" class="inline-flex items-center gap-1.5 text-sm font-medium text-primary hover:text-primary-hover">
<x-icon name="arrow" :size="16" class="rotate-180" /> 返回产品中心