Post 上的真实性令牌无效

Invalid Authenticity Token on Post

我正在使用 devise 签署 up/in。

路线

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

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/profile returns 预期输出。然而,

POST 请求抛出错误提示:

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

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

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

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

<%= csrf_meta_tag %> 

地址通过javascript

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

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

protect_from_forgery with: :exception

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

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

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

  # ...
end

或禁用特定控制器的 CSRF protection

class ProfilesController < ApplicationController
  skip_before_action :verify_authenticity_token

  # ...
end

:null_session 策略清空会话而不是引发异常 ,这非常适合 API。因为会话是空的,所以不能使用 current_user 方法或其他引用 session.

的助手

重要:

  • protect_from_forgery with: :null_session 只能在特定的情况下使用 情况下,例如允许 API 请求 (POST/PUT/PATCH/DELETE) 没有 html 形式
  • 使用 protect_from_forgery with: :null_session 时,您必须使用授权系统限制对数据的访问,因为每个人都可以对您的 API 端点
  • 发出请求
  • 不要删除通过 html 表单完成的请求的 protect_from_forgery with: :exception 很危险!(阅读此处 http://guides.rubyonrails.org/security.html#cross-site-request-forgery-csrf

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

路线

Rails.application.routes.draw do
  resources :profiles

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

end

应用程序控制器

# 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

配置文件控制器

(html 请求的标准控制器)

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

  # POST yoursites.com/profiles
  def create
  end
end

Api::V1::ProfilesController

(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

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