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

Rails API POST请求异常:疑似CSRF验证问题

排查 Rails API 自建网站调用无响应 + CSRF 验证失败问题

我之前也碰到过几乎一模一样的问题,咱们一步步拆解排查:

1. 先确认 protect_from_forgery 的声明顺序

这是最容易踩的坑!Rails 中过滤器的执行顺序是按代码声明顺序来的,protect_from_forgery 必须放在所有 before_action 之前,否则其他前置过滤器已经执行,CSRF 检查早已经触发了。

正确的写法应该是这样:

class ApplicationController < ActionController::Base
  # 必须放在最前面!
  protect_from_forgery with: :null_session

  # 其他前置过滤器比如认证、参数处理放在后面
  before_action :authenticate_user!
end

2. 检查前端请求的头部和格式

Postman 测试正常,大概率是前端请求的格式/头不对:

  • 必须设置 Content-Type: application/json 请求头,否则 Rails 会把请求当作普通表单提交,强制要求 CSRF Token
  • 请求体必须是 JSON 格式,不能是 form-data 或 x-www-form-urlencoded

举个前端 fetch 请求的正确示例:

fetch('https://your-heroku-api.com/posts', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    // 如果有用户认证头(比如JWT)也要加上
    'Authorization': 'Bearer ' + userToken
  },
  body: JSON.stringify({
    post: {
      title: '测试标题',
      content: '测试内容'
    }
  })
})

3. 确认 CORS 配置是否生效

如果你的前端和 API 不在同一个域名下,浏览器会先发一个 OPTIONS 预检请求,要是没配置 CORS,这个请求会被拦截,你看起来是“无响应”,但实际请求根本没到你的 create 方法。

解决方法:

  1. 在 Gemfile 里添加 gem 'rack-cors',执行 bundle install
  2. 在 config/initializers/cors.rb 里配置(记得替换成你的前端域名):
Rails.application.config.middleware.insert_before 0, Rack::Cors do
  allow do
    origins 'https://your-frontend-site.com' # 测试阶段可以用 '*' 允许所有域名
    resource '*',
      headers: :any,
      methods: [:get, :post, :put, :patch, :delete, :options, :head]
  end
end
  1. 重启 Heroku 应用:heroku restart

4. 检查你的异常捕获逻辑

你提到控制器里有 rescue_from ActiveRecord::RecordInvalid,如果这个捕获方法没有正确返回响应,也会导致前端收不到数据,看起来像“无响应”。

正确的异常捕获写法应该是:

class PostsController < ApplicationController
  rescue_from ActiveRecord::RecordInvalid, with: :render_validation_errors

  def create
    @post = Post.new(post_params)
    @post.save! # 用 save! 抛出异常,让 rescue_from 捕获
    render json: @post, status: :created
  end

  private

  def post_params
    params.require(:post).permit(:title, :content)
  end

  def render_validation_errors(exception)
    # 必须明确返回错误响应
    render json: exception.record.errors, status: :unprocessable_entity
  end
end

5. 查看完整的 Heroku 日志

别只看那一句 CSRF 错误,用 heroku logs --tail 实时查看日志,发送请求时看完整的错误栈。有时候 CSRF 错误只是表象,实际可能是参数不合法、数据库连接问题或者认证失败。

比如如果日志里除了 CSRF 错误,还有 ActionController::ParameterMissing,那就是前端没传对参数格式。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.26 08:54:57