安全加固 + 结构清理:修注入/串写/竞态,DOMPurify 上线,后端补事务与 handler 测试
后端: - ORDER BY 白名单(sanitizeOrder)堵住 ?order= SQL 注入,补回归测试 - 登录限速(每 IP 10 次失败/10 分钟 429)、TLS/反代下 Secure cookie、NewAPI 构造器 - Delete/setTags/MergeTags/DeleteTag 包事务;Archive 去 500 篇上限 - 列表接口裁剪:不传 content_md,长文 content_html 截 600,新增 content_len;health 探 DB 前端: - EditorView 路由复用串写修复(RouterView :key + sync watch 回写原文章) - v-html 出口统一过 DOMPurify(sanitizeHtml),stripTags 改 DOMParser - 列表竞态防护(Home/Tag/Posts 请求序号)、TagView 分页修复 - 侧栏接口 30s 缓存去重;one:unauthorized 监听器泄漏修复 - 删 styles.css 498 行重复块;移除 tailwind/marked/vue-tsc 死依赖;CommandPalette a11y 语义
This commit is contained in:
+6
-12
@@ -1,16 +1,11 @@
|
||||
import { marked } from 'marked'
|
||||
import DOMPurify from 'dompurify'
|
||||
|
||||
marked.setOptions({ breaks: true, gfm: true })
|
||||
|
||||
// 编辑器预览与前台渲染共用这一个入口:先 marked 渲染,再过 DOMPurify
|
||||
export function renderMarkdown(text) {
|
||||
return DOMPurify.sanitize(marked.parse(text || '', { async: false }))
|
||||
// 后端 goldmark 已转义原始 HTML,这里再过一道 DOMPurify 作纵深防御,
|
||||
// 所有 v-html 出口必须经过它。
|
||||
export function sanitizeHtml(html) {
|
||||
return DOMPurify.sanitize(html || '')
|
||||
}
|
||||
|
||||
// 编辑器按 `md.render(...)` 的用法调用
|
||||
export const md = { render: renderMarkdown }
|
||||
|
||||
// 用 Intl.DateTimeFormat — locale 感知,未来要 i18n 只换 locale 即可
|
||||
const longDateFmt = new Intl.DateTimeFormat('zh-CN', {
|
||||
year: 'numeric',
|
||||
@@ -50,9 +45,8 @@ export function relativeDate(iso) {
|
||||
}
|
||||
|
||||
export function stripTags(html) {
|
||||
const div = document.createElement('div')
|
||||
div.innerHTML = html || ''
|
||||
return div.textContent || ''
|
||||
// 不用 div.innerHTML:那会真正解析并触发 <img onerror> 之类的事件
|
||||
return new DOMParser().parseFromString(html || '', 'text/html').body.textContent || ''
|
||||
}
|
||||
|
||||
// 短文在列表里没有标题,用正文首句当索引
|
||||
|
||||
Reference in New Issue
Block a user