2013-04-28 63 views
187

當我碰到一些真實性令牌問題時,我正在開發新的Rails 4應用程序(在Ruby 2.0.0-p0上)。Rails 4真品令牌

在寫一個控制器,響應JSON(使用respond_to類的方法),我到了create行動我開始ActionController::InvalidAuthenticityToken例外,當我試圖創建一個使用curl紀錄。

我確定我設置了-H "Content-Type: application/json",並將數據設置爲-d "<my data here>",但仍然沒有運氣。

我嘗試使用Rails 3.2編寫相同的控制器(在Ruby 1.9.3上),並且我沒有任何真實性令牌問題。我搜索了四周,我發現Rails 4中的真實性令牌發生了一些變化。根據我的理解,它們不再自動插入到表單中了?我想這會以某種方式影響非HTML內容類型。

有什麼辦法可以解決這個問題,而不必申請一個HTML表單,搶走真實性標記,然後用該標記發出另一個請求?還是我完全錯過了一些完全明顯的東西?

編輯:我只是想用一個支架不改變任何東西在一個新的Rails創造了新的記錄4應用程序,我遇到了同樣的問題,所以我想這不是我做的事。

回答

270

我想我只是想通了。我改變了(新)的默認

protect_from_forgery with: :exception 

protect_from_forgery with: :null_session 

按照註釋中ApplicationController

# Prevent CSRF attacks by raising an exception. 
# For APIs, you may want to use :null_session instead. 

您可以通過在源尋找request_forgery_protecton.rb,或者更具體地說,下面幾行看到了差距:

Rails 3.2

# This is the method that defines the application behavior when a request is found to be unverified. 
# By default, \Rails resets the session when it finds an unverified request. 
def handle_unverified_request 
    reset_session 
end 

Rails 4

def handle_unverified_request 
    forgery_protection_strategy.new(self).handle_unverified_request 
end 

這將調用the following

def handle_unverified_request 
    raise ActionController::InvalidAuthenticityToken 
end 
+20

你可以一起刪除:with選項:null_session是默認值:http://api.rubyonrails.org/classes/ActionController/RequestForgeryProtection/ClassMethods.html – Casey 2013-08-20 20:29:52

+5

有沒有辦法使用異常的非JSON JSON調用(aka API調用)的調用和空會話? – 2014-01-09 14:38:05

+0

@JamesMcMahon您可以編寫自己的'before_action'來檢查格式和請求是否被驗證。我不知道任何建立條件的方式。 – alexcoco 2014-01-09 15:11:35

31

我不認爲通常關閉CSRF保護是不好的,只要你不專門實現一個API。

在查看關於ActionController的Rails 4 API文檔時,我發現您可以關閉每個控制器或每個方法庫的僞造保護。

例如關閉的方法CSRF保護您可以使用

class FooController < ApplicationController 
    protect_from_forgery except: :index 
+0

這對我來說是在Rails 4中做的 - 試圖刪除後拋出錯誤。 ^^ – 2014-09-26 13:54:28

67

而是關閉CSRF保護的,最好是下面的代碼行添加到窗體

<%= tag(:input, :type => "hidden", :name => request_forgery_protection_token.to_s, :value => form_authenticity_token) %> 

如果您使用form_for或form_tag生成表單,則會自動將以上代碼行添加到表單中

+9

如果您正在製作表單,這是一個很好的建議,但問題在於使用JSON進行API調用。 – 2014-01-09 14:34:32

+1

儘管謝謝,這回答了我在使用手柄時手寫代碼的問題! – DerProgrammer 2014-07-02 21:48:12

65

將以下行添加到表單中工作對我來說:

<%= hidden_field_tag :authenticity_token, form_authenticity_token %> 
+12

並不適用於api調用 – courtsimas 2014-04-15 16:03:25

+2

比上面的代碼更簡潔。謝謝! – DerProgrammer 2014-07-02 21:48:55

+2

就我而言,我使用的是Rails4。我可以通過點擊提交按鈕來提交表格。但是,如果我通過JS代碼提交表單,則會發生此錯誤。這個答案解決了我的問題。 – 2014-07-25 10:37:22

0

當你定義你自己的HTML表單,那麼你必須包含身份驗證令牌字符串,應發送到控制器出於安全原因。如果您使用Rails表單助手來生成真實性標記,則按以下方式添加到表單中。

<form accept-charset="UTF-8" action="/login/signin" method="post"> 
    <div style="display:none"> 
    <input name="utf8" type="hidden" value="&#x2713;" /> 
    <input name="authenticity_token" type="hidden" value="x37DrAAwyIIb7s+w2+AdoCR8cAJIpQhIetKRrPgG5VA="> 
    </div> 
    ... 
</form> 

因此,解決問題的辦法是要麼添加authenticity_token場或使用軌道形成的助手而不是損害安全性等

+1

謝謝你的回答,雖然這不回答原來的問題。這個問題是關於響應JSON請求的問題,但您提供的是一種從頭開始的HTML表單的解決方案。在提出JSON請求(認爲API)時,您並未提交HTML表單,並且您可能無法輕鬆訪問真實性標記。 – alexcoco 2014-07-06 13:20:16

+0

,除非請求的內容實際上是JSON,在這種情況下,您希望將其設置爲「application/json」。 – alexcoco 2014-07-06 13:35:31

+0

我明白答案不完全是你要找的。但相關答案的目的是幫助用戶尋找類似的「真實性問題」。 – amjad 2014-07-06 13:39:50

8

在同樣的問題來了。通過添加到我的控制器修復它:

 skip_before_filter :verify_authenticity_token, if: :json_request? 
+0

未定義的方法'json_request?'爲#,任何想法? – Deano 2016-03-23 12:30:39

+0

你必須在那裏定義一個方法: def json_request? request.format.json? 結束 – 2016-12-28 06:01:55

6

您試過嗎?

protect_from_forgery with: :null_session, if: Proc.new {|c| c.request.format.json? } 
2

這些功能。
但是,要回答你的問題,這裏有一些輸入。 您可以在控制器名稱後添加這些行。

像這樣,

class NameController < ApplicationController 
    skip_before_action :verify_authenticity_token 

這裏有一些線路不同版本的軌道。

導軌3

skip_before_filter:verify_authenticity_token

導軌4

skip_before_action:verify_authenticity_token


你應該打算禁用該安全功能對所有控制器程序,你可以protect_from_forgery的值更改爲:您application_controller.rb文件null_session

像這樣,

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

如果你正在使用jQuery與軌,警惕允許進入方法未經覈實真實性令牌。

jQuery的UJS可以管理令牌你

你應該有它已經作爲jQuery的軌道寶石的一部分,但你可能需要把它列入的application.js

//= require jquery_ujs 

這就是你所需要的 - 你的Ajax調用現在應該工作

欲瞭解更多信息,請參見: https://github.com/rails/jquery-ujs

1

添加authenticity_token: true到窗體標記

0

我所有的測試都正常工作。但由於某些原因,我已經把我的環境變量,以非測試:

export RAILS_ENV=something_non_test 

我忘了取消設置這個變量,因爲這些我開始ActionController::InvalidAuthenticityToken例外。

未設置$RAILS_ENV後,我的測試重新開始工作。