Rails 5的ActionController::InvalidAuthenticityToken错误

31

我有一个Rails应用程序,计划将其升级到Rails 5。我正在使用devise(v4.2.0)和rails(v5.0.0)。根据devise README.md文件的建议,我尝试将protect_from_forgery移到before_filter上面,但是当我尝试登录或更新时,仍然会出现错误ActionController :: InvalidAuthenticityToken

我的Application Controller如下:

class ApplicationController < ActionController::Base
 protect_from_forgery with: :exception, prepend: true
 before_action :configure_permitted_parameters, if: :devise_controller?

  protected

   def configure_permitted_parameters
     devise_parameter_sanitizer.permit(:sign_up, keys: [:name])
     devise_parameter_sanitizer.permit(:account_update, keys: [:name])
   end

end

我的另一个 BugController

class BugsController < ApplicationController
  protect_from_forgery prepend: true, with: :exception
  before_action :authenticate_user!
  before_action :set_bug, only: [:show, :edit, :update]

    def update
      respond_to do |format|
      if @bug.update(bug_params)
        format.html { redirect_to @bug, notice: 'Bug was successfully updated.' }
        format.json { render :show, status: :ok, location: @bug }
     else
        format.html { render :edit }
        format.json { render json: @bug.errors, status: :unprocessable_entity }
     end
     end
   end

private
def bug_params
  params.require(:bug).permit(:product, :component, :title, :description, :status_id, :created_by_id, :assigned_to_id)
end


end
5个回答

81

Devise文档中所述,针对Rails 5的注意事项:

对于Rails 5,请注意protect_from_forgery不再预置于before_action链中。如果你已经在protect_from_forgery之前设置了authenticate_user,你的请求将会产生"无法验证CSRF令牌真实性"的错误。为了解决这个问题,您可以更改调用它们的顺序,或使用protect_from_forgery prepend: true


8
这似乎比跳过验证真实性令牌的选项要好得多! - Stephen
4
这应该是被选中的答案。 - Tallboy
这个解决方案对我也有帮助。我使用了AWS CloudFront和Route53,并且遇到了类似的问题:我向Rails应用程序(无需登录的反馈表单)发送POST请求,通过HTTP一切正常,没有CSRF令牌,但是通过SSL,Pitost就不能工作了。我需要在CloudFront中添加自定义源头标头来修复“Origin header didn't match request.base_url”的问题,然后我遇到了“Can't verify CSRF token authenticity”的问题,当我将令牌添加到请求并添加标头'X-CSRF-Token': authenticity_token时,我遇到了“InvalidAuthenticityToken”的问题,而这个解决方案帮助了我。 - VoidVolker
谢谢!这很简单。 - Nitesh
这也适用于 Rails 6 吗? - stevec

14

注意:虽然这个答案可以产生期望的效果,但是它通过降低整体安全性来实现。Alon 给出的以下回答更加正确并且保持了网站的安全性。

class BugsController < ApplicationController
skip_before_filter :verify_authenticity_token
protect_from_forgery prepend: true, with: :exception
before_action :authenticate_user!
before_action :set_bug, only: [:show, :edit, :update]
end

像这样


1
我尝试在bugs控制器中加入skip_before_filter :verify_authenticity_token,但仍然无效。 - H D
Bugs controller 中: protect_from_forgery prepend: true, with: :exception before_action :authenticate_user! before_action :set_bug, only: [:show, :edit, :update] - H D
我尝试使用您提供的答案,但仍然出现错误 ActionController::InvalidAuthenticityToken in BugsController#update - H D
6
使用skip_before_action比使用skip_before_filter更好。 - Mauro Nidola
我曾經這樣做過並且有效,但考慮到下面的回覆,我相信這是一個糟糕的答案。 - Ogre Codes
显示剩余3条评论

5

最近我在一个相当大的项目中遇到了这个问题,发现我的应用程序域名已经更改但我忘记更新 session_store.rb 文件。这可能不是所有人的问题,但它会报告 CSRF 错误。所以请确保检查 config/session_store.rb 文件。


FYI,它是config/initializers/session_store.rb文件。我相信。 - hoffmanc

1
我曾使用过类似的东西,对我很有效。
class WelcomeController < ActionController::Base
    protect_from_forgery with: :exception
    before_action :authenticate_model!
end

1

这个决定帮助了我。我从这里得出了决定[1]。就我而言,那个主题的不幸命名使用错误关键字,我找不到它,所以我会在这个线程中放弃,因为这里是错误的确切名称。 在我的情况下,我“添加”了以下行到application_controller.rb文件中:

protect_from_forgery with:: null_session

在这个解决方案中,有一行写着"REPLACE"的地方protect_from_forgery with:: exception,如果存在的话,请将其替换为我上面引用的那个。

   [1]: Rails 4 Authenticity Token


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接