簡體   English   中英

防止兩個用戶從單獨的會話中提交相同的表單數據

[英]Prevent two users from submitting the same form data from separate sessions

我的應用程序是基於表單的應用程序,用戶可以在其中提出請求,將ID分配給該請求,用戶將填寫一些詳細信息,然后通過不同階段提交。 多個用戶可以成為一個請求的一部分的問題,因此可能存在用戶A和用戶B同時查看表單的情況。 用戶A可以先提交,然后用戶B提交,這將導致請求僅顯示用戶B提交的信息。為了解決這個問題,我提出了兩個解決方案:

- 在我們將數據提交給數據庫之前,我們進行了一次調用以查看數據是否已經提交(我們在應用程序中使用了狀態。因此我們將檢查“階段#待定”的狀態)。

- 我們為其他一些服務實現了Redis緩存。 我可以添加類似的東西

public submitRequest() {
  RMap<String, int> requestLockMap = redissonClient.getMap("requestLock");
  if(requestLockMap.get('request_ID') == 0) {
     requestLockMap.put('request_ID', 1);
     ...continue submitting request...
  }
}

這實際上是在Redis Cache中加入競爭條件。 但是,我不知道這種事情是否是一種好習慣。 還有更好的選擇嗎? 我使用Spring作為我們的Java框架,所以如果有任何解決方案,我願意聽取它們的意見。

為每次提交分配隨機生成的ID會有什么缺點?

例如,使用UUID

UUID.randomUUID().toString()

您可以減少相同請求ID在統計上的可能性0.數據庫更新可以視為異常,因為這種情況不太可能發生。

使用此方法還可以避免未經授權的用戶使用先前的請求ID查看/編輯相鄰信息的情況。

不要按照你的第二個解決方案。 如你所說,它很可能會導致競爭條件。

你的第一個建議是正確的。 關鍵是在事務中進行更新,同時檢查狀態是否為預期,以便您可以繼續進行更新。

狀態類似於具有版本ID。 更新條目時,將增加版本ID。 因此,后續/並行編輯將具有無效的版本號或狀態,並且不會繼續。 在您的情況下,如果狀態未處於暫掛狀態,您將無法繼續進行更新。

在事務內部,您可以回滾並向用戶返回錯誤消息,即請求已由用戶X編輯。

但是,如果有許多狀態,則最好使用版本ID而不是狀態。

另一種方法是在update語句的where子句中添加所需的狀態,如此處所示以避免更新已修改的行。

Hibernate有一個內置機制來實現樂觀鎖定 請參閱了解詳情。

我建議在表中有一個時間戳字段,用戶正在更新。 向用戶顯示表單時,請閱讀時間戳並將其保留在會話中。 更新時,執行類似update table A set some_column = 'value', timestamp = now() where id = 1 and timestamp = 'whatever timestamp you read earlier' 然后查看update語句的返回值,如果為1,則更新行,如果為0,則其他用戶已更新 - 向用戶顯示一些錯誤/通知。 當然,您需要在每次更新期間更新時間戳字段。

一種解決方案是使用自動增量整數字段。 當您獲取具有一個值的記錄並將其包含在表單信息中時。 提交表單時,將讀取記錄以查看其是否具有相同的值。 如果是這樣,請提交。 如果沒有,請拒絕並向用戶發送錯誤,告知他們為時已晚。

由於字段在每次提交時自動遞增,因此除了確保提交的表單包含該字段的相同值之外,您不必執行任何操作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM