Files
ny-exam-platform/docs/.vitepress/config.mjs
T
nxxy335 a3be81b261 fix(security): 修复上传名单文件可被 URL 直连访问(nginx 下可 getshell)
严重漏洞:roster_import 使用 $_FILES 的原始扩展名拼 roster_YYYYMMDD_HHMMSS.<ext>
落在 Web 根目录内的 data/uploads/,既无扩展名白名单(可上传 .php),文件名又
可按秒枚举;而 bootstrap 只写了 data/.htaccess,nginx 不读 .htaccess,
生产环境(nginx + PHP-FPM)下可直接远程代码执行。

修复(api.php roster_import 四层防护):
- 扩展名白名单:仅 xlsx / xlsm / csv / txt
- 随机文件名:bin2hex(random_bytes(16)),杜绝枚举
- 解析完成后 @unlink 立即删除,Web 目录下不留存任何上传文件
- 20MB 大小限制 + UPLOAD_ERR 检查

加固(bootstrap.php):data 及 cache/uploads/snapshots 每个目录都写
.htaccess(Deny from all)+ index.html 占位;README 与文档补充 nginx
location ^~ /data/ { deny all; return 404; } 规则。

测试:新增 e2e tools/test-upload-guard.js(11 断言,覆盖 .php/.phtml 被拒、
无残留、合法 csv 导入成功且即删、无可枚举文件名),并入 tests/run-all.sh。
全套 90 项通过。

docs: 新增 VitePress 文档站(18 页)
- 使用指南 12 页:简介/部署/快速上手/系统设置/名单管理/统计口径/试卷设置/
  快照趋势异常/导出打印/数据看板/随机抽取/常见问题
- 安全 2 页:安全总览(含本次漏洞复盘)与部署加固清单(P0-P2)
- 开发 4 页:架构与目录/接口一览/SQLite 存储/测试
- 配图迁移至 docs/public/images/;.gitignore 忽略文档构建产物
2026-09-10 22:42:13 +08:00

130 lines
3.8 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { defineConfig } from 'vitepress'
// 部署到子路径时,构建前设置环境变量即可:
// DOCS_BASE=/ny-exam-docs/ npm run docs:build
const base = process.env.DOCS_BASE || '/'
export default defineConfig({
base,
lang: 'zh-CN',
title: 'NY 问卷考试系统数据平台',
description: '基于 PHP 8 + 卷王(SurveyKing)社区版开放 API 的零依赖考试数据统计平台',
cleanUrls: true,
ignoreDeadLinks: true,
head: [
['meta', { name: 'theme-color', content: '#2563eb' }],
['meta', { name: 'referrer', content: 'no-referrer' }]
],
themeConfig: {
// outlineTitle: '本页目录',
outline: [2, 3],
lastUpdated: { text: '最后更新于' },
search: {
provider: 'local',
options: {
locales: {
zh: {
translations: {
button: { buttonText: '搜索文档', buttonAriaLabel: '搜索文档' },
modal: {
noResultsText: '未找到相关结果',
resetButtonTitle: '清除查询条件',
footer: {
selectText: '选择',
navigateText: '切换',
closeText: '关闭'
}
}
}
}
}
}
},
nav: [
{ text: '首页', link: '/' },
{ text: '使用指南', link: '/guide/introduction', activeMatch: '/guide/' },
{ text: '安全', link: '/security/', activeMatch: '/security/' },
{ text: '开发', link: '/dev/architecture', activeMatch: '/dev/' }
],
sidebar: {
'/guide/': [
{
text: '开始',
items: [
{ text: '平台简介', link: '/guide/introduction' },
{ text: '环境要求与部署', link: '/guide/install' },
{ text: '快速上手', link: '/guide/quickstart' }
]
},
{
text: '核心功能',
items: [
{ text: '系统设置', link: '/guide/settings' },
{ text: '名单管理', link: '/guide/roster' },
{ text: '成绩明细与统计口径', link: '/guide/scores' },
{ text: '试卷设置(满分/合格率/免考)', link: '/guide/project-config' },
{ text: '快照、趋势与异常检测', link: '/guide/snapshot' },
{ text: '导出与打印', link: '/guide/export-print' }
]
},
{
text: '其他页面',
items: [
{ text: '数据看板', link: '/guide/dashboard' },
{ text: '随机抽取', link: '/guide/draw' }
]
},
{
text: '帮助',
items: [
{ text: '常见问题', link: '/guide/faq' }
]
}
],
'/security/': [
{
text: '安全',
items: [
{ text: '安全总览', link: '/security/' },
{ text: '部署加固清单', link: '/security/hardening' }
]
}
],
'/dev/': [
{
text: '开发',
items: [
{ text: '架构与目录', link: '/dev/architecture' },
{ text: '接口一览', link: '/dev/api' },
{ text: '数据存储(SQLite)', link: '/dev/database' },
{ text: '测试', link: '/dev/testing' }
]
}
]
},
socialLinks: [],
footer: {
message: '基于 PHP 8 + 卷王(SurveyKing)社区版开放 API 构建,零第三方运行依赖。',
copyright: 'Copyright © NY 问卷考试系统数据平台'
},
docFooter: {
prev: '上一页',
next: '下一页'
},
returnToTopLabel: '回到顶部',
sidebarMenuLabel: '菜单',
darkModeSwitchLabel: '主题',
lightModeSwitchTitle: '切换到浅色模式',
darkModeSwitchTitle: '切换到深色模式'
}
})