You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用fetch()和原生JavaScript伪造.xhr请求

结论

完全可以实现,没有任何技术障碍。

原理说明

你贴出的是Ruby on Rails框架的标准评论提交处理逻辑,其中request.xhr?的判断规则非常简单,没有任何复杂的客户端指纹校验:它只会检查请求头中是否存在值为XMLHttpRequest的X-Requested-With字段。
jQuery的$.ajax系列方法默认会给所有异步请求自动加上这个请求头,所以原有jQuery代码可以正常拿到评论片段的返回;而原生fetchAPI默认不会携带这个头,服务端会将请求判定为普通非异步请求,走到重定向分支。

实现方案

你只需要在发起fetch请求时,手动在请求头配置里加上X-Requested-With: XMLHttpRequest即可。同域场景下添加这个自定义头不会有任何限制,完全可以被服务端正常识别。
绝大多数Rails站点默认开启CSRF安全校验,你还需要同步携带页面中预置的CSRF令牌,否则请求会被安全策略拦截。

参考实现代码

const commentForm = document.querySelector('#comment-form')
commentForm.addEventListener('submit', async (e) => {
  e.preventDefault()
  const formData = new FormData(commentForm)

  const response = await fetch(commentForm.action, {
    method: commentForm.method.toUpperCase() || 'POST',
    body: formData,
    headers: {
      // 核心配置:添加XHR请求标识
      'X-Requested-With': 'XMLHttpRequest',
      // 携带Rails要求的CSRF令牌
      'X-CSRF-Token': document.querySelector('meta[name="csrf-token"]')?.content
    },
    // 兜底配置:禁止fetch自动跟随重定向
    redirect: 'manual'
  })

  if (response.ok) {
    // 服务端返回的是评论HTML片段,直接插入页面对应位置即可
    const commentHtml = await response.text()
    document.querySelector('.comment-list').insertAdjacentHTML('beforeend', commentHtml)
    commentForm.reset()
  }
})

注意事项

  • 不要给携带FormData的fetch请求手动设置Content-Type请求头,浏览器会自动生成带正确boundary边界值的multipart/form-data头,手动设置会导致服务端无法正常解析表单数据
  • 该方案完全适配同域前端重构场景,跨域场景下这个自定义头会触发CORS预检请求,需要服务端返回对应许可头才能使用,你没有后端权限的情况下跨域场景无法生效,但重构本站前端不存在这个问题
  • redirect: 'manual'是兜底配置,就算头配置出错导致服务端返回重定向,fetch也不会自动触发页面跳转,方便调试定位问题

内容的提问来源于stack exchange,提问作者YmeYnot45

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 06:27:18