Ruby-on-rails 帖子上的真实性令牌无效

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/34251400/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 00:19:28  来源:igfitidea点击:

Invalid Authenticity Token on Post

ruby-on-railsrubyruby-on-rails-3devise

提问by Imran Ahmad

I am using deviseto sign up/in.

我正在使用devise注册/登录。

routes

路线

get 'profile' => 'profile#get_profile'
post 'profile' => 'profile#create_profile'

and profile_controller

profile_controller

def get_profile
    render json: {user: current_user}, status: :ok
end

def create_profile
    render json: {user: current_user}, status: :ok
end

GET:http://localhost:3000/user/profilereturns the expected output. However,

GET: http://localhost:3000/user/profile返回预期的输出。然而,

POSTrequest throws an error saying:

POST请求抛出一个错误说:

ActionController::InvalidAuthenticityToken in User::ProfileController#create_profile.

ActionController::InvalidAuthenticityToken in User::ProfileController#create_profile.

Please demystify this behavior.

请揭开这种行为的神秘面纱。

回答by NickGnd

To disable CSRF protectionyou can edit your ApplicationControllerlike this:

要禁用,CSRF protection您可以ApplicationController像这样编辑:

class ApplicationController < ActionController::Base
  protect_from_forgery with: :null_session

  # ...
end

or disable the CSRF protectionfor specific controller:

或禁用CSRF protection特定控制器:

class ProfilesController < ApplicationController
  skip_before_action :verify_authenticity_token

  # ...
end

:null_sessionstrategy empties the session instead of raising an exception which is perfect for an API. Because the session is empty, you can't use current_usermethod or othes helpers that refer to the session.

:null_session策略清空会话而不是引发异常,这对于 API 来说是完美的。因为会话是空的,所以不能使用current_user引用session.

IMPORTANT:

重要

  • protect_from_forgery with: :null_sessionmust be used only in specific cases, for example to allow API request (POST/PUT/PATCH/DELETE) without html form
  • With protect_from_forgery with: :null_sessionyou must restrict access to your data with an authorization system because every one could do request against your API endpoint
  • Don't remove protect_from_forgery with: :exceptionfor requests that are done through html form, is dangerous!(read here http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf)
  • protect_from_forgery with: :null_session必须仅在特定情况下使用,例如允许没有 html 表单的 API 请求 (POST/PUT/PATCH/DELETE)
  • 随着protect_from_forgery with: :null_session你必须限制与授权系统访问您的数据,因为每个人都可以做的请求对您的API端点
  • 不要删除protect_from_forgery with: :exception通过 html 表单完成的请求,是危险的!(在这里阅读http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf

To handle both standard requests (through html form) and API requests generally you have to set up two different controller for the same resource. Example:

要处理标准请求(通过 html 表单)和 API 请求,通常您必须为同一资源设置两个不同的控制器。例子:

Routes

路线

Rails.application.routes.draw do
  resources :profiles

  namespace :api do
    namespace :v1 do
      resources :profiles
    end
  end

end

ApplicationController

应用控制器

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  # Prevent CSRF attacks by raising an exception.
  # For APIs, you may want to use :null_session instead.
  protect_from_forgery with: :exception
end

ProfilesController

配置文件控制器

(standard controller for html requests)

(html请求的标准控制器)

# app/controllers/profiles_controller.rb
class ProfilesController < ApplicationController

  # POST yoursites.com/profiles
  def create
  end
end

Api::V1::ProfilesController

Api::V1::ProfilesController

(controller for API requests)

(API 请求控制器)

# app/controllers/api/v1/profiles_controller.rb
module Api
  module V1
    class ProfilesController < ApplicationController
      # To allow only json request
      protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? }

      # POST yoursites.com/api/v1/profiles
      def create
      end
    end
  end
end

refereces: http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html#method-i-protect_from_forgery

参考:http: //api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html#method-i-protect_from_forgery

回答by Austio

Get requests don't have an authenticity token.

获取请求没有真实性令牌。

You will have to add the request forgery stuff to your forms using this

您必须使用此将请求伪造的内容添加到您的表单中

<%= csrf_meta_tag %> 

And address via javascript

并通过javascript地址

$('meta[name="csrf-token"]')

回答by Jeiwan

In ApplicationController(or another controller your controllers inherit from) there's a line:

ApplicationController(或您的控制器继承的另一个控制器)中有一行:

protect_from_forgery with: :exception

Remove it and CSRF checks will be disabled.

删除它,CSRF 检查将被禁用。