简体   繁体   中英

CSRF Error in Production: ActionController::InvalidCrossOriginRequest

I am getting the following error on my comments controller in my production environments only (works fine in development). The user flow is as follows: I have jQuery that runs when a specific button is pushed which renders a partial file to add a new comment, a simple form. The respond_to method for the .js request in the controller is for new.js.erb file. This should be relatively easy to do but something is going wrong in the Rails (I am using Rails 4.1.1) code or on my server (Rackspace Cloud Server). The error is below:

ActionController::InvalidCrossOriginRequest in CommentsController#new Security warning: an embedded tag on another site requested protected JavaScript. If you know what you're doing, go ahead and disable forgery protection on this action to permit cross-origin JavaScript embedding.

I have tried the following code in my comments controller (does not work). It simply renders the .js file in the browser as a text string (javascript does not work).

protect_from_forgery except: :new
skip_before_action :verify_authenticity_token

I have tried removing the protect_from_forgery with: :exception method in the application_controller.rb file but it does not work (just renders the javascript in the browser as a text string).

I have tried replacing "protect_from_forgery with: :exception" with "protect_from_forgery with: :null_session" and this does not work either (gives the same InvalidCrossOriginRequest error above).

I am running out of options to fix this. Again, it's only happening in production. On my local machine (via localhost), everything works fine. The code for my comments controller is below:

  class CommentsController < ApplicationController
  # before_action :set_comment, only: [:show, :edit, :update, :destroy]
  before_action :load_topic
  before_action :authenticate_user!
  # protect_from_forgery except: :new
  # skip_before_action :verify_authenticity_token

  # GET /comments
  # GET /comments.json
  def index
    @comments = Comment.all
  end

  # GET /comments/1
  # GET /comments/1.json
  def show
  end

  # GET /comments/new
  def new
    @comment = Comment.new
  end

  # GET /comments/1/edit
  def edit
  end

  # POST /comments
  # POST /comments.json
  def create
    @comment = @topic.comments.new(comment_params)
    @comment.user_id = current_user.id
    respond_to do |format|
      if @comment.save
        format.html { redirect_to @topic, notice: 'Comment was successfully created.' }
        format.json { render :show, status: :created, location: @comment }
        format.js
      else
        format.html { redirect_to @article, alert: 'Unable to add comment' }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
        format.js { render 'fail_create.js.erb'}
      end
    end
  end

  # PATCH/PUT /comments/1
  # PATCH/PUT /comments/1.json
  def update
    respond_to do |format|
      if @comment.update(comment_params)
        format.html { redirect_to @comment, notice: 'Comment was successfully updated.' }
        format.json { render :show, status: :ok, location: @comment }
      else
        format.html { render :edit }
        format.json { render json: @comment.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /comments/1
  # DELETE /comments/1.json
  def destroy
    @comment = @topic.comments.find(params[:id])
    @comment.destroy
    respond_to do |format|
      format.html { redirect_to @topic, notice: 'Comment was successfully deleted.' }
      format.json { head :no_content }
      format.js
    end
  end

  private

    def load_topic
      @topic = Topic.find(params[:topic_id])
    end

    # Use callbacks to share common setup or constraints between actions.
    def set_comment
      @comment = Comment.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def comment_params
      params.require(:comment).permit(:topic_id, :body, :name)
    end
end

Any advice on fixing this issue would be appreciated.

Has this actually happened to real users or are you only seeing this error in your logs/monitoring?

This error tends to happen when crawlers are visiting your site (which obviously doesn't happen in your development environment).

The documentation is suggesting you add these to your controller action:

skip_before_action :verify_authenticity_token, if: :json_request?

protected

def json_request?
  request.format.json?
end

However, if this is not the case, I think you actually have a CORS problem. 2 possible reasons:

  • Is your site available via HTTP and HTTPS? These are different origins!
  • Do you have multiple domains running this site? Try to inspect/log the request headers and see if there is any difference in the Origins.

You can try reproducing this in development too, if you edit your hosts file and point a domain to your local server.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM