2014-07-02 20 views
0

在編寫的應用中看到一些奇怪的行爲。我有一個顯示記錄列表的索引頁。如果我創建了一條新記錄,它將被插入到數據庫中,然後用戶被重定向到現在顯示新記錄的索引頁面。每條記錄都有一些AJAX投票鏈接。當用戶單擊新項目上的投票鏈接時,我看到控制器使用兩個不同的IP地址處理了兩次請求......另外,我將每個用戶的永久性cookie中的UUID存儲起來,第二個IP地址顯示與當前用戶不同的UUID。在控制器上處理兩次Rails JS鏈接

我只在我朋友的辦公室看到過這個問題,所以我不知道是因爲他們的網絡搞亂了什麼(公司網絡與代理/防火牆/等等......我被告知管理不善)。我認爲奇怪的是,它只發生在新記錄上,而不是在預先存在的記錄上單擊表決鏈接(使用相同的確切代碼)時...

以下是顯示控制器響應的日誌 - 注意一個響應被處理as JS和第二as */*

Started GET "/vote/14?vote_value=-1" for <company's external IP> at 2014-07-02 16:31:41 -0400 
Processing by FoosController#voting as JS 
    Parameters: {"vote_value"=>"-1", "foo_id"=>"14"} 
    Foo Load (0.7ms) SELECT "food".* FROM "food" WHERE "food"."id" = $1 ORDER BY created_at DESC LIMIT 1 [["id", "14"]] 
    (0.3ms) BEGIN 
    SQL (0.8ms) INSERT INTO "votes" ("created_at", "updated_at", "uuid", "value", "foo_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Wed, 02 Jul 2014 20:31:41 UTC +00:00], ["updated_at", Wed, 02 Jul 2014 20:31:41 UTC +00:00], ["uuid", "61230391-311a-4358-9c4b-665d2a8bc8e9"], ["value", -1], ["foo_id", 14]] 
    (2.0ms) COMMIT 
    (0.2ms) BEGIN 
    (0.3ms) COMMIT 
    Rendered foo/voting.js.erb (0.1ms) 
Completed 200 OK in 14ms (Views: 2.2ms | ActiveRecord: 4.3ms) 


Started GET "/vote/14?vote_value=-1" for <different unrecognized IP> at 2014-07-02 16:31:41 -0400 
Processing by FoosController#voting as */* 
    Parameters: {"vote_value"=>"-1", "foo_id"=>"14"} 
    Foo Load (0.6ms) SELECT "food".* FROM "food" WHERE "food"."id" = $1 ORDER BY created_at DESC LIMIT 1 [["id", "14"]] 
    (0.3ms) BEGIN 
    SQL (0.7ms) INSERT INTO "votes" ("created_at", "updated_at", "uuid", "value", "foo_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", Wed, 02 Jul 2014 20:31:41 UTC +00:00], ["updated_at", Wed, 02 Jul 2014 20:31:41 UTC +00:00], ["uuid", "b8a23470-9f9f-4a65-8577-7da7e31a6995"], ["value", -1], ["foo_id", 14]] 
    (1.7ms) COMMIT 
    (0.1ms) BEGIN 
    (0.1ms) COMMIT 
    Rendered foo/voting.js.erb (0.2ms) 
Completed 200 OK in 13ms (Views: 2.4ms | ActiveRecord: 3.5ms) 

下面是局部的,其中包括AJAX鏈接的記錄:

<div class="foo" id="foo-<%= foo.id %>"> 
    <div class="voting"> 
    <span id="foo-<%= foo.id %>-score"><%= foo.score %></span> 
    <div class="voting-links" id="foo-<%= foo.id %>-voting-links"> 
     <%= link_to 'UP', voting_path(foo.id, vote_value: 1), remote: true %>/
     <%= link_to 'DOWN', voting_path(foo.id, vote_value: -1), remote: true %> 
    </div> 
    </div> 

    <div class="foo-content" id="foo-<%= foo.id %>-content"> 
    <%= foo.content %> 
    </div> 
</div> 

這裏是我的控制器操作:

def voting 
    @foo = Foo.find(params[:foo_id]) 

    vote = @foo.votes.create(uuid: cookies[:user_uuid], value: params[:vote_value]) 

    @foo.save 

    respond_to do |format| 
     format.html { redirect_to root_path } 
     format.js { render 'voting' } 
    end 
    end 

和響應js.erb文件:

score = $('#foo-' + <%= @foo.id %> + '-score'); 
score.html(<%= @foo.score %>); 

如何解決這個或者確保它不是一個應用程序的問題,是一個網絡的問題,在這個特別的網站的任何想法?我一直無法在我的辦公室進行復制。我使用Firebug檢查瀏覽器發出的請求,看起來只有一個請求正在發送。這只是一個錯誤配置的網關/路由器/防火牆等問題......以某種方式重現請求?它發送兩個不同的UUID似乎很重要,但我無法想象它爲什麼只發生在新的條目中。

謝謝!

+0

那麼,如果這來自一個單一的位置,你不應該調查你的代碼,除非你需要防止重複輸入。 – Benj

+0

呀到目前爲止它指向外部的問題......我確實打算在防守代碼解決此,但好奇,如果有人見過這或也有類似的問題 – Jim

回答

1

如果它來自單個位置,那麼它不是來自您的代碼。它可能是一個病毒,一個設置不當的緩存代理,一個web掃描器機器人或其他任何東西。

捍衛你的代碼免受重複輸入是件好事,但看起來相當複雜。示例:由於負載平衡代理,您不能依賴源IP。

好歹有個東西,你可以嘗試(我想你必須):

1 - 您使用的是GET請求,我從你的日誌,一個INSERT在你的數據庫做看看。這違背了RESTfull解決方案。只有POST請求應該觸發INSERT。您應該更改您的代碼以反映這種情況,無論這種情況多麼困難

2-一旦您正確設置了該操作的POST請求,則必須強制使用護欄來防止跨腳本請求,方法是使用csrf_meta_tags頭文件和您的控制器中的protect_from_forgery

我的確希望這會解決這種情況,並放棄第二個請求。在開始這樣的修改之前,確保你的測試套件完全覆蓋了你的代碼,因爲這樣一個深刻的變化可能會導致不確定的結果,尤其是AJAX表單或多部分表單。

它很複雜,可能很長,但是現在看到您的日誌似乎您的服務器未受到保護。

+0

我已經改變了得到一個POST(這是一個監督上我的部分),但我已經在我的application.html.erb中使用了<%= csrf_meta_tags%>,並在我的應用程序控制器中使用了protect_from_forgery ...還有其他想法? – Jim

+0

更改GET後,您仍然收到雙重請求嗎? – Benj

+0

會讓你知道我什麼時候可以再次在同一地點測試 – Jim