面试题手册

梳理高频技术问题,帮助你按主题复习和查漏补缺。

前端阅读 05月30日 22:48

whistle 如何捕获请求并快速过滤定位问题?

whistle 捕获请求的核心流程是:启动本地代理,让浏览器、App 或命令行流量经过它,然后在 Network 面板查看请求、响应、耗时、头信息和匹配规则。它不像浏览器 DevTools 只看当前页面,而是能统一观察多端流量,尤其适合排查 H5、客户端内嵌页、Node 服务请求和第三方 SDK 调用。使用前要明确边界:whistle 只能看到走代理的流量,系统代理没配好、App 不信任证书、命令行绕过代理时,Network 面板自然不会出现请求。先启动服务并打开管理页:npm i -g whistlew2 start -p 8899open http://127.0.0.1:8899/浏览器可以直接配置 HTTP/HTTPS 代理为 127.0.0.1:8899,命令行请求可以这样验证:export HTTP_PROXY=http://127.0.0.1:8899export HTTPS_PROXY=http://127.0.0.1:8899curl -I https://example.com如果要看 HTTPS 明文内容,需要安装并信任 whistle 根证书。证书只用于本机调试,别在公共设备或不可信网络里随便安装;调试结束后可以关闭代理,避免正常访问也继续经过 whistle。Network 面板里最常用的是域名、路径、方法、状态码和关键字过滤。排查接口失败时,先用域名缩小范围,再用 status:500、method:POST、接口路径片段继续收窄。遇到请求太多的页面,直接清空列表后复现一次,比在几千条历史记录里搜索更可靠。追问为什么已经配置代理却抓不到请求?先确认流量来源是否真的走了 127.0.0.1:8899,浏览器、系统、App 模拟器和命令行各有自己的代理设置。取舍上,浏览器调试最简单,移动端调试更接近真实场景但证书和网络环境更容易出问题。常见坑是 App 使用了证书锁定、系统代理被 VPN 覆盖,或者 Node 请求库显式禁用了代理。可以先用 curl 走代理验证 whistle 正常,再回到具体客户端排查。Network 里请求太多,怎么快速定位目标接口?不要一上来搜索很短的词,比如 api 或 user,这会把噪音也带进来。更稳的做法是按域名、路径片段、请求方法、状态码逐层过滤,最后再看请求体或响应体。边界是过滤条件越多,越可能把真正的异常请求排除掉,所以每次收窄都要确认列表数量是否合理。踩坑时可以先清屏,再触发一次具体操作,让目标请求出现在最新的几条里。HTTPS 请求显示 CONNECT 或看不到响应体怎么办?这通常是证书没有安装、没有被系统信任,或者客户端不接受用户证书。浏览器调试时安装 whistle 证书一般就够了,Android 7 之后的 App 可能还需要应用允许用户证书,部分金融或安全类 App 会做证书锁定。取舍是:普通业务调试可以信任本机证书,涉及敏感账号和生产数据时应尽量用测试环境。不要为了抓包去关闭应用安全校验并提交到正式包,这是非常典型的安全事故源头。如何用 whistle 判断问题在前端还是后端?先看请求是否发出、URL 和参数是否正确,再看后端返回的状态码、响应体和耗时。若请求没发出,多半是前端逻辑、跨域预检或网络配置问题;若请求正确但响应错误,就要看服务端日志或网关链路。一个实用取舍是临时用规则 mock 一个成功响应,如果页面恢复正常,说明前端渲染链路大概率没问题。反过来,如果 mock 成功响应页面仍异常,就要查前端数据解析或状态管理。过滤和搜索有什么踩坑点?过滤是为了缩小列表,搜索是为了在已有列表里找内容,两者不要混用。很多人只搜响应关键字,却忘了请求还没被捕获或已经被过滤条件排除,结果误以为接口没返回。另一个坑是缓存,请求可能直接走浏览器缓存,Network 里看不到你期待的接口变化。排查时可以禁用缓存、加随机参数,或者在 whistle 里观察状态码和响应头是否真的来自服务端。
前端阅读 05月30日 22:48

whistle Values 如何管理多环境配置和 mock 数据?

whistle 的 Values 可以理解成一份可复用的变量仓库,用来存放域名、端口、token、mock JSON、响应片段等配置。规则里用 {key} 引用后,同一份值可以被多条规则复用,切环境时只改 Values,不用把规则逐行改一遍。它最适合处理“规则稳定但数据经常变”的场景,比如本地、测试、预发三套接口地址,或者同一个接口在不同用例下返回不同响应。边界也要先说清楚:Values 不是数据库,不适合放大量动态数据,更不要放生产密钥;它解决的是代理调试里的配置复用问题。常见启动方式如下,先确认 whistle 正常运行,再进入 http://127.0.0.1:8899/ 管理界面。npm i -g whistlew2 start -p 8899w2 status在 Values 面板里可以创建 env.json,内容保持简单、稳定:{ "apiHost": "http://127.0.0.1:3000", "testHost": "https://test.example.com", "userId": "10001", "profileMock": { "name": "Tom", "role": "admin" }}规则中再引用这些值:^https://api.example.com/(.*) {apiHost}/$1https://api.example.com/user?id={userId} resBody://{profileMock}这个写法的好处是规则仍然表达“流量怎么转发”,Values 只负责“具体值是什么”。如果团队多人共用,建议把 key 命名成 env.apiHost、mock.profile.admin 这类层级语义,避免 host1、data2 这种几天后没人敢动的名字。追问Values 和 Rules 应该怎么分工?Rules 管流量匹配、转发、替换和注入,Values 管可复用的数据。取舍标准很简单:如果一段内容会被多条规则引用,或者经常随环境变化,就放到 Values;如果它只服务一条规则,直接写在 Rules 里反而更直观。踩坑最多的是把整套规则都“变量化”,最后打开规则只看到一堆 {xxx},排查时必须来回切面板。Values 应该降低重复,不应该降低可读性。多环境配置怎么切换最稳?建议为不同环境建独立 Values,例如 local.json、test.json、pre.json,每份保持相同 key,只替换 value。这样规则文件不用变,切换时只启用对应 Values,团队成员也容易对齐。边界是同一时间不要启用多份同名 key 的 Values,否则后加载或更高优先级的值会覆盖前面的值,表现像“规则偶尔失灵”。如果必须临时覆盖,最好在 key 名里写清楚 override,用完立刻关闭。Values 里能不能放接口 mock 响应?可以,尤其适合体积不大的 JSON 响应、错误码、空列表、权限状态等固定场景。取舍在于维护成本:几十行以内的 mock 放 Values 很方便,几百行甚至带复杂逻辑时,应该改用文件、插件或脚本处理。常见踩坑是 JSON 少了引号或多了尾逗号,规则没有明显报错,但响应内容就是不对。写 mock 时先用 JSON 校验工具检查,再用 Network 面板确认最终响应体。Values 适合保存 token 和账号信息吗?临时调试 token 可以放,但不建议长期保存真实生产凭据。whistle 是本地代理工具,团队共享配置、截图或导出时很容易把敏感值带出去。更稳的做法是只保存占位符,例如 {debugToken},真实值由个人本地单独维护,或者在脚本里从环境变量读取。边界是测试环境的低权限 token 可以接受,生产管理员 token 不应该进入 Values。Values 不生效时怎么排查?先看 key 是否拼错,再看对应 Values 是否启用,最后看规则命中是否符合预期。可以把响应临时改成固定文本验证引用是否成功,例如 resBody://{profileMock},比直接排查完整代理链更快。另一个坑是值里包含特殊字符、换行或 URL 参数时没有正确转义,导致规则解析和预期不同。排查时一次只改一个变量,并在 Network 里查看实际请求 URL、响应头和响应体。
前端阅读 05月30日 22:48

whistle 支持哪些协议?HTTP、HTTPS、WebSocket 怎么代理?

Whistle 常用于 HTTP 调试,但它能处理的并不只有普通 HTTP 请求。前端和移动端排查里,常见的是 HTTP、HTTPS、WebSocket、HTTP/2 以及 SOCKS 或上游代理。理解这些协议的差异,比背规则更重要:HTTP 明文好改,HTTPS 需要证书信任,WebSocket 建连后是长连接,HTTP/2 可能在代理链路里被降级。协议边界没弄清,规则看似正确,请求也可能不按预期走。HTTP 最直接,可以替换 host、改请求头和响应体,适合本地联调和 Mock。www.example.com host 127.0.0.1:8080http://www.example.com/api/user resBody://{"code":0}http://www.example.com/api/user reqHeaders://{"x-debug":"1"}HTTPS 多了一层证书。浏览器先和代理建立 CONNECT,再由 whistle 解密转发;没有信任根证书时,只能看到隧道,看不到路径和响应。调试前先启动服务并按页面提示安装证书:w2 start -p 8899# 浏览器访问 http://127.0.0.1:8899,下载并信任根证书HTTPS 的坑主要有三个:移动端证书信任策略不同;部分 App 做了证书固定;生产登录、支付链路不该随便关闭校验。调试时可以只匹配目标域名,不要用过宽规则影响全部流量。WebSocket 也是 whistle 很有价值的场景。它先通过 HTTP Upgrade 建立连接,之后变成双向消息流,因此排查时既要看握手,也要看消息内容。ws://socket.example.com host 127.0.0.1:7001wss://socket.example.com host 127.0.0.1:7001HTTP/2 和 SOCKS 更像链路兼容问题。很多代理工具会把 HTTP/2 在中间链路降到 HTTP/1.1,这通常不影响接口语义,但会影响多路复用、头压缩和性能判断。SOCKS 适合把流量再转给公司代理、远程调试机或特定网络出口,改包能力仍然发生在 whistle 这一层。api.example.com socks://127.0.0.1:1080api.example.com proxy://http://127.0.0.1:8888追问HTTP 和 HTTPS 代理规则写法一样吗?大部分匹配和改写规则看起来一样,但 HTTPS 能否生效取决于证书信任和解密权限。HTTP 请求是明文,whistle 可以直接看到路径、header 和 body;HTTPS 如果只建立了 CONNECT 隧道,就只能看到域名和连接信息。取舍是安全性和可调试性:本地排查可以信任证书,生产或敏感链路不要随意解密。遇到规则不生效,先确认是不是根本没拿到 HTTPS 明文。WebSocket 代理为什么有时只能看到连接,看不到消息?可能是规则只命中了握手域名,没有命中实际的 wss 地址,也可能是客户端走了不同端口或备用域名。WebSocket 建连成功后是长连接,页面刷新、重连和心跳都会影响观察结果。另一个常见坑是消息被业务层压缩或加密,代理能看到帧,但看不懂业务内容。排查时先验证 Upgrade 状态,再看消息方向和重连次数。HTTP/2 被代理后降级会不会影响测试结论?如果只是验证接口返回、Mock 数据和 header,通常影响不大。若你在排查性能、连接复用、服务端推送或 gRPC 类场景,降级就可能改变结论。whistle 更适合做功能调试和流量改写,不适合替代专门的协议性能分析工具。边界看测试目标:测业务语义可以接受,测协议特性就要谨慎。SOCKS、proxy 和 host 规则怎么选?host 适合把目标域名指到本地或测试机,最直观也最常用。proxy 适合把请求交给另一个 HTTP 代理,socks 适合走公司网络、远程环境或特定出口。不要把三者叠太多层,否则失败时很难判断是哪一层断了。建议先用 host 跑通,再按网络限制加上游代理。多协议混合项目应该怎么写规则?不要用一个大规则覆盖所有域名,应该按协议和业务域名拆开。HTTP API、HTTPS 登录、WebSocket 推送、静态资源最好分别写,必要时加注释说明用途。这样做的成本是规则文件稍长,但排查时能快速关闭某一段,不会影响其他流量。尤其是移动端项目,登录和长连接经常共享域名,规则过宽很容易制造假故障。
前端阅读 05月30日 22:48

whistle 如何和浏览器、IDE、构建工具一起调试?

Whistle 和开发工具集成时,核心思路不是“装越多插件越好”,而是把它放在请求链路中最容易观察和改写的位置。DevTools 看页面行为,IDE 编辑规则,构建工具跑本地服务,whistle 统一接住请求。同一个接口问题可以从页面、代理、服务端交叉验证。取舍也很明显:链路越完整,排查能力越强,但配置层级越多,误配概率也越高。最基础的集成是浏览器代理。Chrome、Edge、Firefox 都可配置系统代理,也可只给调试浏览器加启动参数。w2 start -p 8899/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --user-data-dir=/tmp/chrome-whistle --proxy-server=http://127.0.0.1:8899这种方式适合排查登录、Cookie、CORS、缓存和重定向。DevTools 是页面侧视角,适合看瀑布图和前端报错;whistle 是代理侧视角,适合改响应、替换 host、保存规则。HTTPS 调试要先安装 whistle 根证书,否则只能看到 CONNECT,无法看到明文请求。IDE 集成更简单,重点是让规则文件进项目。VS Code 可以用普通文本编辑规则,WebStorm 可以同时配置 HTTP Client 和项目代理。团队协作时,建议把常用规则放进仓库:# local-api.rulesapi.example.com host 127.0.0.1:3000static.example.com file:///Users/me/project/mock-statichttps://api.example.com/debug reqHeaders://{"x-debug":"1"}构建工具不要盲目再代理一次。Vite、Webpack、Next.js 都能转发 /api,如果它们和 whistle 同时改 host,排查会很绕。稳妥方案是:构建工具只跑前端页面,跨域、Mock、弱网和接口替换交给 whistle。// vite.config.jsexport default { server: { proxy: { '/api': { target: 'http://127.0.0.1:8899', changeOrigin: true } } }}追问浏览器 DevTools 已经能看 Network,为什么还要 whistle?DevTools 擅长观察,但不擅长批量改写和复用规则。whistle 可以把 host 替换、响应 Mock、请求头注入、弱网模拟保存成规则,下一次不用重新点一遍。两者不是替代关系,DevTools 看页面表现,whistle 控制网络入口。边界是性能分析仍然优先看 DevTools,因为它能关联渲染、脚本和资源加载时间。VS Code 插件是必须的吗?不是必须,规则本质上是文本,能编辑、能保存、能被团队复用就够了。插件的价值主要是语法高亮和减少拼写错误,不应该依赖插件才能跑通流程。真正容易踩坑的是规则只存在某个人本机 whistle 里,换机器就复现不了。建议把关键规则文件放进项目,并说明启动端口和适用环境。Vite 或 Webpack 的 proxy 和 whistle 会冲突吗?会,尤其是两边都配置了 /api 转发或 host 替换时,请求路径会变得不直观。一般建议本地开发服务器只服务前端资源,把接口层交给 whistle;如果项目已有 devServer proxy,就让它转到 whistle 统一分流。这样牺牲了一点配置简洁度,但换来更稳定的调试入口。排查时按浏览器、devServer、whistle、后端的顺序逐层确认。和 Postman、curl 这类接口工具怎么配合?接口工具可以直接把代理设成 127.0.0.1:8899,或者临时使用环境变量。这样请求会经过 whistle,便于复用同一套 Mock 和 header 规则。命令行可以这样跑:HTTPS_PROXY=http://127.0.0.1:8899 curl https://api.example.com/user -k。注意 -k 只适合本地调试,真实证书问题不能靠它掩盖。团队共用 whistle 规则有什么风险?最大风险是规则过期但没人知道,导致新人调试时命中了旧环境。另一个坑是规则过宽,例如只写 example.com host 127.0.0.1,把静态资源、登录和接口全改掉。团队规则应该小而明确,按场景拆分,并在注释里写清楚用途和失效条件。需要经常变化的个人规则,不要混进公共规则。
前端阅读 05月30日 22:48

whistle 如何接入自动化测试并稳定 Mock 网络请求?

Whistle 可以接入自动化测试,但它更适合作为“可控网络层”,而不是替代测试框架。Jest、Playwright、Puppeteer 负责断言和驱动浏览器,whistle 负责代理、Mock 和改包。这样测试代码不用侵入业务接口,也能复现弱网、跨域和接口异常。边界也要说清楚:如果只是单元测试,直接 mock 函数更轻;只有涉及浏览器真实网络、HTTPS 或 WebSocket 时,whistle 的价值才明显。先把 whistle 作为测试前置服务启动,端口固定,避免 CI 和本机不一致。npm i -D jest puppeteernpm i -g whistlew2 start -p 8899w2 stop浏览器侧只需要把代理指向 whistle。Puppeteer 的配置通常放在测试 setup 里,Playwright 也有类似的 proxy 选项。const browser = await puppeteer.launch({ headless: 'new', args: ['--proxy-server=http://127.0.0.1:8899']})Mock 规则建议单独维护,不要散落在测试用例里。比如把线上 API 改到本地服务,或者直接返回固定 JSON:api.example.com host 127.0.0.1:3000https://api.example.com/user resBody://{"code":0,"name":"mock-user"}https://api.example.com/user resHeaders://{"content-type":"application/json"}在 CI 里要额外处理两个细节:第一,等待 whistle 真正启动后再跑测试,不能只 sleep 一秒就赌运气;第二,HTTPS 场景需要提前安装并信任 whistle 根证书。测试环境可临时加 ignoreHTTPSErrors,但它会掩盖证书链问题,不适合验证支付、登录链路。追问Jest、Playwright 和 Puppeteer 该选哪个?如果测试重点是函数和组件逻辑,Jest 足够,没必要引入 whistle。只要验证真实页面请求、跳转、Cookie 或跨域行为,就应该用 Playwright 或 Puppeteer 驱动浏览器,再让 whistle 接管网络。Playwright 在多浏览器和等待机制上更省心,Puppeteer 更贴近 Chrome 调试。取舍点是维护成本:端到端测试越真实,运行越慢,也越容易受环境影响。Mock 数据应该写在 whistle 规则里还是测试代码里?稳定的接口替身适合写成 whistle 规则,因为规则可以被开发、测试和 CI 复用。和断言强相关的一次性数据,可以放在测试代码里,避免规则文件变成没人敢改的“黑盒”。踩坑最多的是两边都写,最后不知道哪个 Mock 生效。建议给规则文件加命名约定,例如 e2e-login.rules。HTTPS 自动化测试为什么经常失败?最常见原因是证书没有被系统或浏览器信任,whistle 能看到请求,但页面侧直接阻断。另一个坑是某些客户端启用了证书固定,代理解密会失败,这类场景只能做旁路抓包或在测试包关闭 pinning。CI 容器里还要注意证书安装路径,不同镜像的信任库不一样。不要把 ignoreHTTPSErrors 当万能药,它只能让浏览器继续跑,不能证明 HTTPS 链路真的没问题。如何判断 whistle 规则真的被测试用例命中了?不要只看页面断言通过,还要检查网络侧是否经过预期域名和规则。可以在 whistle 界面查看请求,也可以让被 Mock 的响应返回测试专用字段,例如 x-mock-source: whistle-e2e。如果接口被浏览器缓存,规则可能根本没走,所以测试前最好禁用缓存或给请求加唯一 query。定位失败时先验证代理配置,再验证规则匹配,最后看业务断言。什么时候不该把 whistle 放进自动化测试?纯算法、纯组件渲染和后端接口契约测试,不需要 whistle,直接 mock 或启动本地服务更快。whistle 适合解决“网络路径不可控”的问题,不适合承担所有测试隔离职责。规则过多会让测试变慢,也会让新人很难理解真实请求链路。一个实用边界是:只有当问题必须在浏览器代理层复现时,才把它纳入 whistle 自动化测试。
服务端阅读 05月30日 22:17

什么是 CSRF 攻击?它如何工作,又该怎么防护?

CSRF(跨站请求伪造)不是偷 Cookie,而是借浏览器自动带 Cookie 的机制,冒充用户发起操作。典型流程是:用户已经登录 bank.example,浏览器里有登录 Cookie;随后用户打开攻击者页面,页面自动提交一个转账、改邮箱或删除数据的请求;请求发到 bank.example 时,浏览器会按域名自动带上 Cookie。服务器如果只看 Cookie 判断“用户已登录”,却不校验这次操作是不是从本站页面主动发起,就会把伪造请求当成真实操作。CSRF 成立通常要同时满足几个条件:用户处于登录状态;目标站使用 Cookie、Session 这类浏览器会自动携带的凭证;接口会改变状态;服务端没有校验 CSRF Token、Origin、Referer 或 SameSite 等额外信号。少了其中任何一环,攻击难度都会明显上升。追问CSRF 和普通跨域请求有什么关系?很多人以为浏览器有同源策略,所以 CSRF 发不出去,这是误解。同源策略主要限制攻击者读取跨站响应,不能阻止浏览器发送表单、图片、脚本、跳转这类请求。CSRF 往往不需要读响应,只要服务器执行了“改状态”的动作,攻击就已经成功。CORS 也是类似道理:它控制前端脚本能不能读取响应,不等于所有跨站请求都被拦截。尤其是普通表单提交、图片加载、顶级导航,本来就不依赖 CORS 成功读取响应。GET、POST、JSON API 都会被 CSRF 打中吗?GET 如果只做查询,风险相对小;但如果 GET 做删除、改状态、触发任务,就非常危险,因为 <img>、<script>、<a> 都能轻易触发 GET。POST 表单同样能被恶意页面自动提交,所以“改成 POST”不是完整防护。JSON API 的攻击门槛高一点,因为 application/json 和自定义请求头通常会触发 CORS 预检。但如果服务端错误放开 CORS,或者接口同时兼容表单格式,仍然可能被利用。接口设计上应坚持:读操作和写操作分离,写操作必须带额外校验。CSRF Token 为什么有效?CSRF Token 的作用是证明“请求来自服务端渲染或授权过的本站页面”。服务端生成一个不可预测的随机值,放在页面、meta 标签或接口返回里,前端提交写请求时把它放进隐藏字段或 X-CSRF-Token 请求头。攻击者页面不能读取目标站页面内容,也就拿不到这个随机值。Token 不能随便设计:不要放 URL 里,避免进入日志和 Referer;要绑定用户会话或登录态;过期策略要合理;高风险操作可以使用一次性 Token。Token 校验失败时,应该返回明确的 403,并记录来源、用户、接口和 request id,方便排查误杀。SameSite、Origin、Referer 应该怎么配合?现代防护通常是组合拳。Cookie 设置 SameSite=Lax 可以挡住大量跨站 POST 和 iframe 场景;SameSite=Strict 更安全,但会影响外部链接跳转后的登录体验;必须跨站携带 Cookie 时才用 SameSite=None; Secure。服务端还可以校验 Origin,没有 Origin 时再看 Referer。这两者适合做来源判断和日志审计,但不建议作为唯一防线,因为隐私策略、代理、旧浏览器或特殊跳转可能让头部缺失。更稳的策略是:SameSite 降低默认风险,Token 验证操作意图,Origin/Referer 做辅助拦截。XSS 会不会绕过 CSRF 防护?会。只要攻击者能在你的页面里执行脚本,就可能读取非 HttpOnly 的 CSRF Token,或者直接在同源上下文里调用接口。也就是说,CSRF Token 不能替代 XSS 防护。所以安全设计要分层:Cookie 使用 HttpOnly、Secure、SameSite;页面输出要做转义和 CSP;写接口校验 Token 和来源;高风险操作再加二次确认、幂等号或重新输入密码。不要指望一个机制解决所有问题。示例下面是一个最简单的 CSRF 攻击示例。用户只要打开攻击页面,浏览器就会向目标站发起请求:<form action="https://bank.example/transfer" method="POST"> <input name="to" value="attacker"> <input name="amount" value="1000"></form><script>document.forms[0].submit()</script>服务端防护可以这样做:app.post('/transfer', requireLogin, csrfCheck, async (req, res) => { await transfer(req.user.id, req.body.to, req.body.amount); res.json({ ok: true });});function csrfCheck(req, res, next) { const token = req.get('x-csrf-token') || req.body.csrf_token; if (!token || token !== req.session.csrfToken) return res.sendStatus(403); next();}这段逻辑的重点不是代码长短,而是把“用户已登录”和“用户确实从本站页面发起操作”分开验证。CSRF 正是利用了很多系统只验证前者、忽略后者的漏洞。
服务端阅读 05月30日 21:29

CSRF 是冒充用户,XSS 是控制浏览器吗?

可以这样理解:CSRF 是攻击者借用户身份办事,XSS 是攻击者把脚本塞进页面里办事。CSRF 不一定能读取用户数据,它更关心“让服务器执行一个动作”;XSS 则运行在目标网站页面上下文中,能读页面内容、调同源接口、窃取可访问的 Token,危害范围通常更大。追问CSRF 为什么叫冒充用户?因为请求到达服务器时带着用户的登录 Cookie,看起来像用户自己发起。攻击者不需要知道密码,也不需要拿到 Cookie 内容。XSS 为什么叫控制浏览器?XSS 恶意代码运行在目标网站页面里,能访问当前页面允许访问的资源,比如表单内容和同源接口。两者防护会互相替代吗?不会。CSRF Token 解决请求意图校验,输出编码和 CSP 解决脚本注入执行,保护层面不同。实战最常见误判是什么?以为 POST 就不会被 CSRF,或以为 HttpOnly 就没有 XSS 风险。两种判断都不完整。示例<img src="https://app.example.com/change-email?email=a@evil.com"><img src=x onerror="fetch('/api/profile')">
服务端阅读 05月30日 21:29

如何防御 CSRF 攻击才不会只防住一半?

防御 CSRF 的核心,是阻止攻击者借浏览器自动携带 Cookie 的能力替用户发起敏感请求。只要登录态放在 Cookie 里,转账、改邮箱、删数据、改密码这类接口都要按跨站诱导来防。稳妥方案是 CSRF Token 打底,再配合 SameSite、Origin 校验和高风险操作二次确认。追问为什么自定义请求头能缓解 CSRF?普通跨站表单、图片、脚本请求不能随意带 X-CSRF-TOKEN。攻击者若用 fetch 加自定义头,会触发 CORS 预检。SameSite=Lax 够不够?对普通站点很有帮助,但不能当唯一防线。浏览器兼容、跨站跳转、第三方嵌入和历史客户端都会带来边界。双重提交 Cookie 有什么限制?它把 Token 同时放在 Cookie 和请求参数里。若子域可写 Cookie 或站点有 XSS,攻击者可能伪造或读取 Token。发现漏洞后优先修哪里?先修所有依赖 Cookie 登录态的写接口,尤其是资金、权限、账号资料和删除类操作。随后补自动化测试。示例<input type="hidden" name="csrf_token" value="{{token}}">
服务端阅读 05月30日 21:29

SameSite Cookie 为什么能防止 CSRF?实际配置怎么写?

SameSite Cookie 能防止 CSRF,是因为它把“跨站请求是否携带 Cookie”的决定权交给浏览器。攻击者可以在自己的网站里放自动提交表单或隐藏图片,请求你的站点;但如果浏览器因为 SameSite 策略不发送登录 Cookie,服务端就无法把这次请求识别成已登录用户操作。追问SameSite 防的是哪类 CSRF?它主要防攻击者借浏览器自动带 Cookie 发起的跨站状态修改请求,比如隐藏表单 POST、图片触发 GET 副作用等。Lax 为什么适合作默认值?Strict 会让外部跳转进入站点时也不带 Cookie,体验较差。Lax 保留顶级 GET 导航登录体验,同时拦住更危险的跨站提交。哪些 Cookie 可以设置 None?只有确实需要跨站发送的 Cookie 才应该设置 None,比如第三方登录状态、嵌入式组件或跨站 SSO 临时票据。SameSite 和 CORS 是一回事吗?不是。CORS 决定前端脚本能否读取跨源响应,SameSite 决定跨站请求是否携带 Cookie。写段配置Set-Cookie: session=abc; Secure; HttpOnly; SameSite=Lax; Path=/
服务端阅读 05月30日 21:29

Spring Boot 如何正确实现 CSRF 防护?

Spring Boot 里的 CSRF 防护不要一上来就关掉。只要项目还依赖浏览器 Cookie 维持登录态,POST、PUT、DELETE 这类改数据请求就可能被第三方页面借用户身份发出去。正确做法是保留 Spring Security 的 CSRF 校验:服务端生成 Token,前端在表单或请求头里带回,服务端再验证它是否属于当前会话。追问CookieCsrfTokenRepository 为什么要 withHttpOnlyFalse?SPA 需要从 Cookie 读取 Token,再写入 X-CSRF-TOKEN 请求头。代价是脚本也能读到它,所以站点存在 XSS 时风险会被放大。CSRF Token 和 SameSite 是二选一吗?不是。SameSite 是浏览器层面的减风险措施,Token 是服务端验证用户意图。敏感业务最好两者都用。AJAX 一直 403 查哪里?先看 header 名称是否正确,Spring 常用 X-CSRF-TOKEN。再看 Token 是否来自同一会话,登录刷新、多标签旧页面提交都可能不匹配。什么时候可以忽略 CSRF?真正无状态 REST API 使用 Authorization Bearer,浏览器不会自动带这个头,CSRF 风险较低;但 Session Cookie API 不能直接忽略。写段配置.csrf(csrf -> csrf.csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse()))
服务端阅读 05月30日 21:29

什么是 CSRF 攻击?它需要满足哪些攻击条件?

CSRF 是跨站请求伪造,核心不是偷走用户信息,而是借用用户已经登录的身份去发请求。只要目标站点依赖 Cookie 判断登录态,浏览器又会在请求目标域名时自动带上 Cookie,攻击者就可能诱导用户打开恶意页面,让目标站误以为这次修改密码、转账、删除数据是用户本人操作。它通常需要:用户已登录、目标操作靠 Cookie 认证、接口缺少额外意图校验、攻击者能构造可触发请求。追问CSRF 为什么能利用 Cookie?浏览器发送 Cookie 看的是请求目标域名,不看请求是不是用户主动点的。恶意站不能读取 Cookie,但能诱导浏览器带 Cookie 发请求。哪些接口最容易被打中?所有会改变状态的接口都要重点看,比如转账、改邮箱、改密码、删除数据、绑定账号。GET 接口如果偷偷做写操作也很危险。CORS 拦住跨域响应还有 CSRF 风险吗?有。CORS 主要限制攻击者读取响应,CSRF 很多时候只需要请求被执行,不需要看到结果。实际项目怎么防?常见组合是 CSRF Token + SameSite Cookie + Origin/Referer 校验。Token 证明页面来自本站,SameSite 降低自动带 Cookie 概率。示例<form action="https://bank.example/transfer" method="POST"> <input name="to" value="attacker"></form><script>document.forms[0].submit()</script>
前端阅读 05月30日 21:29

SameSite Cookie 如何防护 CSRF?Strict、Lax、None 怎么选?

SameSite Cookie 防护 CSRF 的关键是让浏览器在跨站请求里少带或不带 Cookie。CSRF 成立,是因为用户登录后,攻击站能诱导浏览器向目标站发请求,而浏览器会自动附带登录 Cookie。SameSite 改变的就是这个默认行为。追问Strict、Lax、None 怎么选?Strict 最严格,适合后台、支付、改密等安全优先页面,但会影响从外部链接进入的登录体验。Lax 是多数业务默认选择;None 只给确实需要跨站携带 Cookie 的场景,并必须配 Secure。SameSite=Lax 能完全替代 CSRF Token 吗?不能。Lax 能挡住大量跨站 POST,但覆盖不了所有业务边界。资金、权限、账号安全仍应保留 Token。SameSite=None 为什么必须配 Secure?因为 None 允许跨站携带 Cookie,现代浏览器要求它只能在 HTTPS 下使用。少了 Secure,很多浏览器会拒收。子域名之间算跨站吗?通常不算。a.example.com 和 b.example.com 在 SameSite 语义下属于同站,因此子域名安全会影响整体站点。写段配置Set-Cookie: sid=abc; Path=/; HttpOnly; Secure; SameSite=LaxSet-Cookie: admin_sid=def; Path=/admin; HttpOnly; Secure; SameSite=Strict
服务端阅读 05月30日 21:29

CSRF 和 XSS 有什么区别?项目里如何区分和防护?

CSRF 和 XSS 都是 Web 安全高频问题,但攻击点完全不同。CSRF 是“冒充用户发请求”:攻击者利用用户已登录的 Cookie,让服务器执行用户并不想做的操作。XSS 是“让脚本跑进用户页面”:攻击者把恶意 JavaScript 注入目标站上下文里,读取页面、窃取 Token、调用接口甚至进一步发起 CSRF。区分时记一句话:CSRF 主要骗服务器,XSS 主要控制浏览器。追问两者攻击前提有什么不同?CSRF 通常要求用户已登录目标站,且敏感接口只靠 Cookie 认证。XSS 要求页面存在输入输出处理漏洞。为什么 XSS 往往更危险?XSS 拿到的是页面执行权,可以读取 DOM、调用接口、窃取非 HttpOnly Token,还可能绕过很多 CSRF 防护。HttpOnly Cookie 能防哪一种?HttpOnly 防止 XSS 直接读 Cookie,但不能阻止脚本发同源请求,也不能单独防 CSRF。防护策略怎么分工?防 CSRF 用 Token、SameSite、Origin/Referer;防 XSS 用输出编码、CSP、避免危险 API 和 HttpOnly/Secure Cookie。示例<form action="https://bank.example/transfer" method="POST"></form><script>fetch('/api/me')</script>
服务端阅读 05月30日 21:29

Referer 头能防护 CSRF 吗?验证时有哪些局限?

Referer 校验能作为 CSRF 防护的一层辅助判断,但不适合当唯一防线。它的做法是对会改变状态的请求,服务端读取 Referer 请求头,确认发起页面来自可信站点;如果来自陌生域名、格式非法或缺失,就拒绝或进入更严格校验流程。它能挡住不少粗糙的跨站表单攻击,但受浏览器隐私策略、Referrer-Policy、HTTPS/HTTP 跳转、代理和客户端实现影响。追问Referer 和 Origin 有什么区别?Origin 只包含协议、域名和端口,不包含完整路径,隐私暴露更少,也更适合安全校验。Referer 信息更完整,但更容易被策略裁剪。没有 Referer 的请求要不要拒绝?管理后台、转账、改密等敏感操作建议拒绝。普通业务可以要求 CSRF Token 通过,并记录日志观察误杀比例。验证 Referer 最常见绕过点是什么?把 includes('example.com') 当安全判断,可能被 example.com.evil.com 绕过。应解析 URL 后比较 hostname。Referrer-Policy 会影响吗?会。no-referrer 可能完全不发 Referer,strict-origin-when-cross-origin 跨站只发源信息。上线前要检查站点策略。写段代码const url = new URL(req.get('referer') || '');if (url.protocol !== 'https:' || !TRUSTED.has(url.hostname)) return res.sendStatus(403);
服务端阅读 05月30日 21:29

双重提交 Cookie 如何防护 CSRF?实现时要注意什么?

双重提交 Cookie 防护 CSRF 的核心是:服务端生成随机 token,同时让浏览器把它放在 Cookie 里,并要求前端在表单字段或请求头里再提交一份。真正的同站页面能读到这份非 HttpOnly 的 CSRF Cookie,所以能把 token 放进请求;恶意站点虽然能诱导浏览器自动带上 Cookie,却读不到目标站 Cookie,也就很难提交同一份 token。服务端比较两边是否一致,就能拦住大多数跨站伪造请求。追问它和传统 CSRF Token 有什么区别?传统 Token 通常保存在服务端 Session 里,请求来了拿提交值和 Session 值比对。双重提交 Cookie 不存服务端状态,更适合分布式和无状态接口,但要更小心 XSS、子域名和 Cookie 覆盖问题。Cookie 能不能设置 HttpOnly?普通双重提交模式下不能,因为前端需要读取 Cookie 后放进请求头或表单字段。更安全的变体是签名双重提交,避免攻击者伪造结构正确的 token。为什么不建议把 token 放 URL?URL 会进入浏览器历史、代理日志、服务端访问日志和第三方统计系统。Token 更适合放请求头或 POST body。最容易踩什么坑?Domain 配太宽,任意子域问题都可能影响主站;只判断字符串相等,没有处理缺失、长度不等和异常输入,也会留下边界问题。写段代码res.cookie('csrf_token', token, { httpOnly:false, secure:true, sameSite:'lax', path:'/' });if (req.cookies.csrf_token !== req.get('x-csrf-token')) return res.sendStatus(403);
服务端阅读 05月30日 21:21

React、Vue、Angular 中如何正确实现 CSRF 防护?

在 React、Vue、Angular 里做 CSRF 防护,关键不是框架语法,而是把服务端发的 CSRF Token 稳定带到每个状态变更请求里。只要登录态依赖 Cookie,前端就要配合后端完成 Token 获取、请求头注入、过期重试和错误提示;如果认证完全使用 Authorization 头,CSRF 压力会小很多,但 XSS 和 Token 存储风险会变高。追问前端应该从哪里拿 CSRF Token?常见方式是服务端在首屏 HTML meta 标签写入 Token,或提供 /csrf-token 接口初始化获取。也可用非 HttpOnly 的 XSRF-TOKEN Cookie。React、Vue、Angular 差异大吗?差异主要在封装位置,不在安全原理。React/Vue 通常在 axios 或 fetch wrapper 统一加头,Angular HttpClient 有 XSRF 支持。SPA 里 Token 过期怎么办?服务端返回 419 或 403 时,可以刷新一次 Token 后重放请求;支付、转账、删除这类非幂等操作不要自动重放。CORS 配好了还需要 CSRF 吗?需要。CORS 控制脚本读取响应,不阻止浏览器发出带 Cookie 的写请求。写段代码axios.interceptors.request.use(config => { const token = document.querySelector('meta[name="csrf-token"]')?.content; if (!['get','head','options'].includes((config.method || 'get').toLowerCase())) config.headers['X-CSRF-Token'] = token; config.withCredentials = true; return config;});
服务端阅读 05月30日 21:21

企业级应用如何设计一套可靠的 CSRF 防护架构?

企业级 CSRF 防护不要只靠某个接口临时加 Token,应该做成统一安全能力:入口层先挡明显跨站请求,应用层校验会话和 Token,高风险业务再做二次确认。架构上要兼顾多域名、SSO、微服务、灰度发布和审计,否则规则一上线就可能误伤登录、支付或第三方集成。追问校验放网关还是业务服务?最好两层都做。网关做通用拦截,如 Fetch Metadata 和 Origin 白名单;业务服务做 Token 是否绑定当前用户、租户和操作。Token 应该怎么存?服务端状态 Token 可放 Redis,便于吊销和一次性使用;双提交 Cookie 性能好,但密钥轮换和重放控制要设计清楚。SSO 和多域名会影响 SameSite 吗?会遇到边界。跨站登录跳转可能需要 SameSite=None; Secure,但业务写操作仍要校验 Origin 和 Token。落地最大坑是什么?没有资产清单就全站强制。老系统可能有跨域表单、WebView、第三方回调,应先观测日志再分级灰度。写段配置if ($http_sec_fetch_site = "cross-site") { set $csrf_block 1; }if ($request_method !~ ^(GET|HEAD|OPTIONS)$) { set $csrf_block "${csrf_block}1"; }if ($csrf_block = "11") { return 403; }
服务端阅读 05月30日 21:21

移动应用需要防 CSRF 吗?如何设计更安全?

移动应用通常不容易遇到传统 CSRF,因为原生 App 不会像浏览器那样自动把站点 Cookie 带到任意跨站请求里。但如果 App 使用 WebView、共享 Cookie、深链唤起、第三方登录页,或者后端同时服务 Web 和 App,就仍然要检查“请求是不是用户真实发起”。追问原生 App 用 Bearer Token 还需要 CSRF Token 吗?大多数情况下不需要,因为 Bearer Token 不会被浏览器自动附加。但 Token 存储不安全会转成账号接管风险。WebView 为什么要特别小心?WebView 容易把 Web 的 Cookie 机制带回来,尤其是内嵌 H5、登录页和支付页。要限制可加载域名和不必要的 JavaScript Bridge。深链会引入什么风险?深链能成为触发器。危险操作不能打开链接后直接执行,必须让用户确认,并由服务端校验幂等号和权限。后端同时支持 Web 和 App 怎么分策略?Web 使用 Cookie + SameSite + Origin + CSRF Token;App 使用 Authorization 头和设备级安全存储。不要让 App 接口默认信任浏览器 Cookie。
服务端阅读 05月30日 21:21

CSRF 防护未来会怎么演进?现在该如何规划?

CSRF 防护未来不会只靠一个 Token,而是会变成“浏览器默认安全能力 + 服务端显式校验 + 风险分层”的组合。现在规划时,优先把 SameSite、Origin/Referer、Fetch Metadata 和关键操作 Token 做成统一基线,再根据业务是否跨站、是否嵌入第三方页面、是否有移动端或开放 API 做例外配置。追问SameSite 变强后还需要 CSRF Token 吗?需要。SameSite=Lax 能挡住很多普通跨站请求,但挡不住所有复杂场景。Token 仍适合关键写操作。Fetch Metadata 能替代传统校验吗?不能完全替代,但适合网关低成本拦截。服务端可根据 Sec-Fetch-Site、Sec-Fetch-Mode 默认拒绝跨站危险方法。CHIPS 和分区 Cookie 会改变模型吗?会改变第三方嵌入场景,但不解决所有业务写操作授权问题。iframe、SSO、第三方插件要提前梳理 Cookie 策略。企业现在怎么改架构?把 CSRF 策略放到统一安全中间件或 API 网关,会话 Cookie 开 Secure、HttpOnly、SameSite=Lax,高风险操作再校验 Token。
前端阅读 05月30日 21:21

RxJS 中 Subject、BehaviorSubject、ReplaySubject 和 AsyncSubject 怎么选?

Subject 是既能订阅又能 next 的 Observable,常用来把外部事件推给多个订阅者。Subject 不保存历史值;BehaviorSubject 保存当前值,新订阅者立刻拿到;ReplaySubject 可以回放一段历史;AsyncSubject 只在 complete 时发出最后一个值。选型时先问:新订阅者要不要旧值,要几个旧值,结果是不是只有完成后才有意义。追问BehaviorSubject 为什么适合状态?状态通常需要当前值,比如用户信息、主题配置、表单快照。它要求初始值,所以你必须明确空状态是什么。ReplaySubject 有什么边界?ReplaySubject 可以保留多个值或一段时间窗口。如果不设置 bufferSize 或 windowTime,历史值可能越攒越多。AsyncSubject 现在还常用吗?比较少,因为很多只取最终结果的场景已被 Promise 或 lastValueFrom 覆盖。它适合只关心完成后最后值的过程。Subject 当事件总线有什么坑?全局事件总线会让数据流来源变模糊。更稳的做法是封装 Subject,只暴露 asObservable。写段代码const currentUser$ = new BehaviorSubject(null);currentUser$.next(user);currentUser$.subscribe(render);