第一次认真研究 X-XSS-Protection 这个响应头是因为一份外部扫描报告。报告里有一条低危告警写着“响应缺少 X-XSS-Protection 头可能存在 XSS 风险”而站点其实已经有比较完整的输出编码规范了。我盯着那条告警想了很久这个头在当下的浏览器里到底还有没有人读配上是加分还是埋雷后来查内核提交记录、翻各家文档、在测试环境里逐个内核验证才发现这个响应头的处境相当尴尬——它是 XSS 防护历史上一段被废弃的尝试如今真正的价值反而是“用来主动关掉一个旧机制”。这篇就把我对X-XSS-Protection的完整理解摊开讲包括它的原始设计意图、值域里每个参数的真实含义、为什么现代内核已经集体无视它、在 Nginx 和应用框架里怎么写才不会重复注入以及一个更关键的问题真正扛住XSS攻击的防线到底长什么样。适合正在处理安全扫描告警的后端和运维同学也适合想搞明白“响应头到底能防到什么程度”的前端同学。1. X-XSS-Protection 的设计初衷一个装在浏览器里的反射型过滤器1.1 它盯的是反射型 XSS不是全部 XSS要理解这个头得先回到它诞生的年代。当时某老牌浏览器厂商在自家内核里塞了一个叫 XSS Filter 的模块思路非常朴素浏览器拿到响应之后把响应体内容和本次请求的 URL包括查询串做一次文本比对如果发现响应体里原样出现了请求参数中的可疑脚本片段就判定这是一次反射型 XSS然后按配置决定是掐掉那段脚本还是干脆不渲染整个页面。这个机制的覆盖面比很多人想象的要窄得多。反射型 XSS 的特征是“攻击载荷必须出现在请求里然后被服务端原样吐回来”过滤器正是抓这个特征。但存储型 XSS 的载荷早就躺在数据库里了跟当前请求毫无关系过滤器看一眼请求 URL 就放过去了DOM 型 XSS 更彻底服务端返回的是干净的 HTML恶意内容完全由客户端脚本在运行时拼出来过滤器连插手的余地都没有。换句话说这个头从设计之初就只能覆盖三类 XSS 里最容易被其他手段解决的那一类。我见过不少团队的误区就在这里以为加了这个头就等于“有 XSS 防护了”结果存储型 XSS 该出还是出而且因为心里觉得有兜底输出编码反而做得更松。这种“安全感的错觉”比完全没防护更麻烦因为它会掩盖真实存在的问题。1.2 值域拆解0、1、1; modeblock 到底差在哪这个头的取值不多但每个值的行为差异很大而且坑基本都藏在“1”这个看起来最正常的默认值里。取值过滤器行为实际风险0完全关闭过滤器不做任何检测无副作用被视为“显式弃用”的推荐写法1启用过滤检测到可疑片段时移除该片段页面其余部分照常渲染启发式判定会误伤可能吃掉正常内容1; modeblock检测到攻击时不渲染整个页面返回空白误判时整页白屏用户体验断崖式下降1; reportURI理论上把检测结果上报到指定地址实际实现极少基本不可用先说0。它的语义是“别管我的页面”浏览器拿到这个值就直接跳过过滤逻辑。很多人第一反应是“这不是自废武功吗”但在今天恰恰相反这是唯一合理的取值原因后面几节会展开。再说1。它是最容易被误用的值因为听起来像“开启防护 更安全”。但它的实际行为是“删除式净化”过滤器发现响应里有一段像脚本的东西就把它从 DOM 里摘掉剩下的继续渲染。问题在于判定逻辑是启发式的字符串匹配不是真正的语法分析。你做一个技术文档站页面里要展示一段scriptalert(1)/script的示例代码过滤器很可能把它当成攻击载荷直接删掉用户看到的就是一段残缺的代码块。这类误伤在生产环境里非常难排查因为服务端返回的内容是对的问题出在浏览器渲染阶段。1; modeblock更激进一旦判定命中就整页不渲染。对于误判来说这等于把“内容缺一块”升级成“整站白屏”风险更高。如果你的站点有大量用户生成内容评论区、个人简介、富文本编辑器回显这个值的误伤概率绝对不低。提示如果你的页面需要展示 HTML/JS 代码片段文档站、教学站、代码分享平台千万不要用1或1; modeblock过滤器的字符串匹配会直接吃掉你要展示的标签。1.3 为什么它最终变成了一段历史2019 年前后Chromium 内核把 XSS Auditor 整个模块移除了官方给出的理由有三条我认为每一条都站得住第一过滤器本身引入了新的攻击面攻击者可以反过来利用“页面被阻断与否”这个信号做侧信道探测甚至在某些组合场景下绕过其他防护第二误报率长期居高不下维护成本远超收益第三现代 Web 应用大量使用框架和动态渲染服务端返回的 HTML 跟最终 DOM 差别巨大基于“请求-响应文本比对”的模型从根上就失效了。移除之后这个头在现代浏览器里就变成了纯粹的 no-op——写着也不报错但也完全不生效。可它并没有从世界上消失因为大量安全扫描器的规则库还停在十年前仍然把“缺少这个头”列为一条问题项。这就形成了一个很荒诞的局面一个已经被证明有害且无人读取的响应头因为合规清单的存在还得继续配。2. 内核态度分化这个头在不同环境下的真实表现2.1 现代内核移除过滤器之后发生了什么先明确一件事移除的是“过滤器”不是“对这个头的解析”。现代 Blink 内核对X-XSS-Protection的处理是直接忽略无论你写0、1还是1; modeblock行为完全一致都是不做任何 XSS 检测。这一点很关键因为它意味着这个头在现代环境下不再是安全控制项而是一个纯配置项——写它的目的不再是影响浏览器行为而是影响扫描器和审计工具的判断。以 Gecko 为代表的内核从来没有实现过这套过滤器所以它对这个头的态度一直是“不认识、不处理”。WebKit 系早期有过类似实现后来也逐步收敛。至于已经停止维护的旧版 Trident 内核那是唯一真正把这个头当回事的环境但它的市场占有率在今天已经可以忽略不计。我实测过一组对照同一份带反射型载荷的页面分别在现代内核和旧内核环境下访问现代环境下载荷照常执行因为服务端没做输出编码旧内核环境下被拦截。这个结果说明的问题很直接——如果你依赖这个头做防护那你实际上是在给一个几乎不存在的用户群体做防护而真正的风险敞口现代浏览器完全没有被覆盖。2.2 一张实测对照表把不同环境下的行为整理成表格方便你判断自己需不需要为兼容性操心。运行环境是否读取该头实际表现是否值得兼容现代 Blink 内核浏览器解析但忽略任何取值均不触发过滤不需要Gecko 内核浏览器不识别完全忽略不需要新版 WebKit 内核不识别完全忽略不需要旧版 Trident 内核读取并执行按取值过滤或阻断极低优先级老旧移动端 WebView取决于内核版本部分版本仍生效需要评估存量服务端扫描器 / 审计工具读取响应头文本按规则库判定合规性这才是主要受众这张表的核心结论是这个响应头的“用户”已经不是浏览器而是扫描器。理解这一点后面的配置决策就顺理成章了——你要优化的不是浏览器行为而是让配置既满足审计要求又不给任何真实存在的旧内核留下误伤空间。2.3 “配了没用”和“配了更危险”为什么同时成立这两句话看起来矛盾其实说的是两个不同的取值。配0是“没用”因为现代内核本来就不读配1或1; modeblock是“更危险”因为它会在仍然读取这个头的旧内核上触发启发式过滤造成内容误伤甚至整页白屏而它拦下的那点反射型攻击用一行输出编码就能彻底解决。我遇到过一个挺典型的案例某内部管理系统为了通过一次安全检查在网关统一加了X-XSS-Protection: 1; modeblock。系统里有个工单详情页用户提交的描述会被原样回显这里本来就该做编码但历史代码没做。上线后陆续有用户反馈“点开某几个工单页面就白屏”排查了两天才定位到这个头——因为某些工单描述里带了类似标签的文本触发了过滤器的阻断逻辑。最后的修复方式是先补输出编码再把响应头改成0。这件事的教训是用响应头去补输出编码的窟窿等于用一个不可控的启发式机制去掩盖一个确定性的代码缺陷。3. 三层落地配置网关、应用框架、中间件怎么加才不冲突3.1 反向代理层的加头方式与两个隐藏坑在 Nginx 里加头最常见的就是add_header但这个方法有两个必须知道的坑。第一个是状态码范围默认情况下add_header只对 200、201、204、206、301、302、303、304、307、308 这些状态码生效4xx 和 5xx 响应不会带上你加的头。安全扫描器经常会把错误页也扫一遍结果就是“首页有这个头404 页面没有”告警依然存在。解决办法是加上always参数。# 在 http、server 或 location 块中 add_header X-XSS-Protection 0 always;第二个坑是继承规则这个比第一个更隐蔽。Nginx 的add_header有一套特殊的继承逻辑只要子块比如某个location里出现了任何一条add_header指令它就不再继承父块server或http里的所有add_header。也就是说你在server层配好了全套安全头然后在某个location里为了加一条缓存控制头写了一行add_header Cache-Control ...这个 location 下的所有安全头就全部消失了。这类问题在大型配置里极难发现因为大部分页面正常只有特定路径缺头。如果上游服务自己也设置了这个头还会出现重复。Nginx 默认不会去重两条同名头会一起发给浏览器。这时候要么让上游别设要么用proxy_hide_header把上游的藏掉proxy_hide_header X-XSS-Protection; add_header X-XSS-Protection 0 always;用了第三方 headers 模块的环境还可以用more_set_headers它的语义是“覆盖”而不是“追加”处理重复头更省心more_set_headers X-XSS-Protection: 0;3.2 应用侧统一注入找一个地方管到底比起到处加更稳的做法是在应用层设一个统一出口让所有响应都经过它。不同技术栈的写法不一样但原则是一样的只在一个地方设置其他地方一律不碰。Java 生态里如果用了成熟的安全框架通常有现成的头管理入口Bean SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.headers(headers - headers .xssProtection(xss - xss .headerValue(XXssProtectionHeaderWriter.HeaderValue.DISABLED)) ); return http.build(); }需要注意不同大版本的框架对这个 API 的处理有差异有的版本默认值本身就已经是0有的版本把相关方法标记为过时并推荐统一走头配置集合。升级框架时如果发现这个头突然变了值先去看框架的默认头策略而不是怀疑网关。Node 生态里一行中间件就够app.use((req, res, next) { res.setHeader(X-XSS-Protection, 0); next(); });注意如果你同时在用某个流行的安全头中间件它早期版本会自动注入X-XSS-Protection: 1; modeblock新版本文档里可能已经找不到这个选项了。升级依赖时务必用curl -I复核一遍实际发出的头不要只看配置文件。Python 生态同理挂在请求后置钩子上最省事app.after_request def apply_security_headers(resp): resp.headers[X-XSS-Protection] 0 return resp3.3 重复头排查一条命令定位问题层排查响应头问题最有效的工具就是curl -I逐层打从最外层往里推。# 打网关 curl -sI https://your-domain/ | grep -i x-xss-protection # 打应用直连地址绕过网关 curl -sI http://10.0.0.10:8080/ | grep -i x-xss-protection如果网关返回一条、应用直连返回一条说明两边都在设必须去掉一边。如果网关返回两条说明上游有一条、网关又加了一条。如果某个路径下一条都没有去检查那个location块里是不是有别的add_header把继承打断了。浏览器侧也要看一眼。开发者工具的 Network 面板里Response Headers 会原样列出所有同名头如果看到两行x-xss-protection基本可以确定是重复注入。不同实现对重复头的取值策略不完全一致有的取第一个、有的取最后一个所以千万别指望“后设的会覆盖前面的”一定要从源头消除重复。3.4 一份可以直接抄的响应头基线把安全头当成一组来配比单独盯着某一个更有意义。下面这份是我在多数 Web 服务上会用的基线按需裁剪# 阻断 MIME 类型嗅探避免上传文件被当成脚本执行 add_header X-Content-Type-Options nosniff always; # 控制 Referer 泄露的粒度 add_header Referrer-Policy strict-origin-when-cross-origin always; # 显式关闭旧内核的 XSS 过滤器 add_header X-XSS-Protection 0 always; # 收敛浏览器能力按业务实际需要放开 add_header Permissions-Policy camera(), microphone(), geolocation() always; # 跨域隔离降低旁路攻击面 add_header Cross-Origin-Opener-Policy same-origin always;CSP 没有放进这份基线因为它必须按站点实际情况定制直接抄一条严格的策略大概率会把站点打挂。这部分放到下一节单独说。4. 真正的防线CSP、输出编码与 Trusted Types 怎么配合4.1 CSP 的收紧节奏别一上来就打死自己内容安全策略才是现代 XSS 防护的主力。它的逻辑跟旧式过滤器完全不同不是去猜哪段内容是恶意的而是白名单式地规定哪些脚本可以执行。页面里就算被注入了一段script只要它不在白名单里、没有正确的 nonce浏览器直接拒绝执行。这是从“事后补救”变成“事前限制”的思路转换也正是旧过滤器做不到的。上来就配最严的策略基本等于自爆正确姿势是三步走。第一步用只上报模式跑一段时间收集真实违规add_header Content-Security-Policy-Report-Only default-src self; script-src self; report-uri /csp-report always;这个阶段不影响任何功能只是把“如果启用会拦掉什么”记录到你的上报端点。跑一两周把上报日志按指令和来源域名聚合你会看到一堆意料之外的调用某个统计脚本、某个客服组件、某个老页面里的内联事件。这一步的价值就是把这些历史包袱摸清楚。第二步处理内联脚本。业务代码里大量onclick...和script.../script是收紧 CSP 最大的阻力解决办法是给每个响应生成随机 nonce# 注意nonce 必须每次请求随机生成绝不能写死 add_header Content-Security-Policy default-src self; script-src self nonce-$request_id; object-src none; base-uri none; frame-ancestors self always;这里必须强调一个高频错误nonce 写死等于没写。有些人图省事把 nonce 配成固定字符串攻击者只要读到一次页面源码就能拿到这个值然后构造带同样 nonce 的注入脚本防护完全失效。nonce 的生命周期必须是单次请求。第三步才是收紧default-src和script-src把unsafe-inline彻底去掉。这个过程可能要配合前端改造比如把内联事件改成addEventListener、把第三方脚本的加载方式统一管理。4.2 输出编码按上下文区分别一把梭很多人对输出编码的理解停留在“把转成lt;”这在 HTML 文本节点里够用但换个位置就完全失效。编码的本质是根据数据将要落入的上下文选择对应的转义规则因为不同上下文的“危险字符”根本不一样。输出位置转义对象关键点HTML 文本节点 最基础的一层覆盖大部分场景HTML 属性值同上属性值必须加引号否则空格都能造成截断JS 字符串字面量 \ / 及换行必须额外处理/scriptURL 参数encodeURIComponent只对参数值编码不要对整个 URL 编码CSS 属性值十六进制转义非必要不要往 CSS 里塞用户输入表格里最容易被忽略的是 JS 字符串那一行。假设你的页面里有这么一段var nickname % user.nickname %;如果用户把昵称设成/scriptscriptalert(1)/script浏览器解析 HTML 的时候会先遇到这个/script直接判定脚本块结束后面的内容就变成了新的 HTML注入成功。这里的防御不是简单转义引号而是必须把/转成\/让/script变成\/scriptHTML 解析器就不会提前闭合标签了。HTML 属性的坑则在于引号。如果你的模板写成div class% value %属性值没加引号攻击者提交一个带空格的字符串就能注入新属性比如x onmouseoveralert(1)。规范写法永远是div class% value %引号是硬性要求不是风格问题。4.3 Trusted Types 与净化库的搭配用法即使 CSP 配得再严只要代码里还有innerHTML userInput这种写法风险就一直在。Trusted Types 解决的就是这个问题它把一批危险的 DOM 赋值入口改成只接受“可信类型”对象普通字符串传进去直接抛异常。在 CSP 里加两条指令就能启用add_header Content-Security-Policy require-trusted-types-for script; trusted-types default; default-src self always;启用之后下面这行代码会直接报错// 抛 TypeError: This document requires TrustedHTML assignment el.innerHTML userInput;这时候必须显式声明你信任这段内容// 用净化库处理后再赋值 const clean DOMPurify.sanitize(userInput); el.innerHTML clean; // 净化库内部通过 trustedTypes.createPolicy 创建策略落地时的现实问题是改造量。老项目里innerHTML可能有几百处一次性改完不现实。我的做法是先在生产环境用只上报模式观察按页面维度统计违规来源优先改造用户输入能直接触达的那几个页面其余的先加进白名单策略里逐步迁移。这个过程中净化库是必需品因为一旦你决定“信任”某个字符串就必须确保它真的被净化过否则等于把防护拆了。4.4 分层防护模型每一层各自管什么把上面这些手段串起来能看到一个清晰的分层结构。每一层解决的是不同层面的问题任何一层单独拿出来都不够但叠起来之后就形成了纵深。层次手段主要拦截的问题局限输入层类型校验、长度限制、白名单明显异常的输入无法判断语义层面的恶意内容输出层上下文相关的编码绝大多数注入型 XSS遗漏一处就前功尽弃执行层CSP 白名单、nonce未授权的脚本执行配置错误会导致大面积功能异常DOM 层Trusted Types、净化库客户端动态拼接导致的注入改造量大需要持续治理凭据层Cookie 的 HttpOnly 属性会话劫持只保护凭据不阻止 XSS 本身监控层CSP 上报、异常行为告警发现绕过和新型攻击属于事后发现不能预防这张表最想说明的一点是X-XSS-Protection不在这张表里的任何一行。它既不是输出编码也不是 CSP更不是监控它只是一个已经被废弃的、附着在浏览器内部的一段启发式逻辑。把它当成防护体系的一环等于在防线外面挂了一块牌子。5. 踩坑实录扫描告警、误伤回退与灰度验证5.1 扫描器为什么还在报这个头这个问题我被问过很多次。原因不复杂大量被动扫描器和合规检查工具的规则库是多年前写的规则本身是“响应头中不存在 X-XSS-Protection 则报低危”。这些工具不会去判断“这个头在当前浏览器内核下是否还有意义”它们只做字符串匹配。处理方式有三条路我按推荐程度排序。第一条也是最省事的干脆配上X-XSS-Protection: 0。这个取值没有任何副作用既不会触发旧内核的过滤因为是显式关闭又能让扫描器的字符串匹配通过。这条路的妙处在于你配的不是防护而是“我明确知道这个机制该关掉”这个事实。第二条在扫描器的规则配置里把这一项加到忽略列表并在报告里注明原因——适合能控制扫描器配置的团队。第三条走流程申诉说明该头已被主流内核移除。实际做下来第一条的性价比最高因为它一次性解决所有拿着旧规则库来扫你的第三方。注意配0的时候要确保全站所有响应都带上包括 404、500 这类错误页否则扫描器换个路径又能报出一条。这就是前面强调always参数的原因。5.2 回退到 0 而不是直接删掉动机在哪这个问题值得单独说因为它涉及一个思维方式的转变。删掉这个头等于让旧内核走默认行为——而默认行为通常就是启用过滤器。也就是说你的“什么都不做”在旧环境下等同于“启用了一个有误伤风险的启发式机制”。配上0则是显式声明“别动我的页面”。我所在的团队在一次内容型站点的改造中就吃过这个亏。当时为了“清理无用配置”把一行X-XSS-Protection: 1; modeblock直接删了觉得反正在新浏览器里没影响。结果存量的一批老旧终端访问时因为有用户提交的内容里带了看起来像标签的文本过滤器开始工作页面出现局部内容缺失。后来改回显式0才彻底解决。这件事之后我的原则就固化了对一个已知有害的旧机制正确的做法是显式关闭而不是放任它走默认值。5.3 灰度上线与回归验证清单改响应头看起来是个小动作但影响面是全站必须有验证流程。下面这份清单是我每次调整头策略时都会过一遍的。第一步配置改完先在预发环境验证用curl -I打三类路径正常页面、带参数的搜索页、错误页。确认三类响应的头完全一致没有重复、没有缺失。for path in / /search?qtest /not-exist-page; do echo $path curl -sI https://your-domain${path} | grep -iE x-xss-protection|content-security-policy|x-content-type-options done第二步功能回归重点盯住三类页面有富文本回显的页面评论区、个人资料、有代码展示的页面文档、帮助中心、有第三方组件嵌入的页面客服、统计、地图。这三类是响应头变更最容易出问题的地方。第三步如果同时在动 CSP一定要先跑只上报模式把上报日志按页面路径和违规指令统计一遍确认违规量级在可接受范围内再切正式模式。切换当天盯着错误监控和前端异常上报CSP 拦截会导致脚本直接不执行表现是“页面能打开但交互全废”这类问题用户不会主动反馈只能靠监控发现。第四步改完一周内复扫一次安全扫描器确认告警项关闭同时确认没有新增其他告警。有些扫描器对 CSP 的判定很严格加了策略反而会引出新的提示需要一并处理。最后分享一个我在实际操作中的体会响应头这类东西最怕的不是配错而是配了之后没人验证、没人知道它为什么在那儿。我现在习惯在每个自定义头的上方写一行注释说明“为什么是这个值”比如X-XSS-Protection: 0旁边就写清楚“显式关闭旧内核过滤器避免误伤现代内核已忽略”。半年后接手的人看到这行注释就不会再纠结要不要把它改成1了。这个习惯看起来琐碎但它省下的沟通成本远比写注释的那几分钟多。
企业数字化 ERP 产品动态
相关推荐
企业知识管理系统(KMS)的核心功能与落地实践 1. 知识管理系统的时代价值十年前我刚入行时,团队还在用共享文件夹管理项目文档,重要信息散落在各种邮件和聊天记录里。直到参与了一个跨国协作项目,才真正体会到知识管理系统(KMS)的价值。当时我们团队分布在三个时区… · 2026/11/3 15:01:20
Vibe Coding方法论争议:直觉编程的缺陷分析 1. 关于"Vibe Coding"的争议背景 最近在编程社区里,一种名为"Vibe Coding"的编程方法论引发了激烈讨论。这种方法论声称通过特定的"氛围"和"感觉"来指导编程实践,主张程序员应该更多地依赖直觉而非严格的逻辑思… · 2026/11/3 15:00:18
天气接口为什么重要:从终端服务到行业气象应用的连接方式 在手机天气、旅游规划、无人机作业、智能空调和赛事保障等场景中,用户看到的往往只是一个温度或降雨提示,背后却涉及数据采集、预报模型、接口调用、风险识别和业务决策等多个环节。对于企业来说,天气接口不仅是“获取天气数据”的工具&#… · 2026/11/3 19:01:01
Ventoy 持久化教程:一次建好 persistence.dat,U盘 Linux 数据跟着走 Ventoy 持久化教程:一次建好 persistence.dat,U盘 Linux 数据跟着走 【免费下载链接】Ventoy A new bootable USB solution. 项目地址: https://gitcode.com/GitHub_Trending/ve/Ventoy
Ventoy 持久化解决的烦恼很具体:从 U 盘启动的 … · 2026/11/3 18:59:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46
STM32F411RE与MAX14431实现SPI隔离:工业现场抗共模干扰实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
ESP32+大模型AI硬件开发:从Demo到产品的8个工程问题 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
基于MAX14431BAEE+与PIC18F85J10的SPI隔离方案设计与实践 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 1:01:59
双极步进电机控制实战:DRV8818PWPR与PIC18F86K22驱动调试 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/2 13:10:28
STM32F207ZG + DRV8818PWPR 步进电机驱动实战解析 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 6:04:24
DRV8818PWPR+dsPIC30F4013工业级双极步进电机控制方案 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/11/3 5:52:46