2016-10-21 93 views
3

我們正在構建一個Web應用程序,並且在前端顯示服務器端驗證錯誤消息時遇到了一些問題。如何顯示服務器端驗證錯誤消息?

給予一定的情況下,我們運行其中的前端是在asp.net react.js和後端API實現了一個單頁的應用程序。我們要求用戶填寫我們的應用程序中有許多表單,並且我們計劃在客戶端和服務器端實現表單驗證。

我們現在遇到的工作流程是先做客戶端驗證,然後將數據傳遞到後端API。後端將首先執行相同的驗證前端,以確保請求不是來自繞過了客戶端驗證規則的惡意用戶。對於來自正常渠道的請求,它應該永遠不會失敗,如果確實如此,那就意味着我們正在處理黑客。

但是,有一點比服務器端驗證。有客戶方不知道的信息,例如銀行賬戶用戶是否在我們的數據庫中存在? (我們沒有專門的api來驗證這一點,所以我們必須在用戶將整個表單提交給服務器端之後在表單級別執行此操作)。

所以在最後,也有服務器端驗證規則兩個部分:與前端,以及先進的驗證規則,需要訪問數據庫是僅適用於服務器端共享基本的驗證規則。

現在的問題是,我們怎麼通知用戶後,他們失敗這兩種類型的驗證嗎?

下面是我們已經走過約兩個提案至今

解決方案1 ​​:使用HTTP 400 - 錯誤的請求表示企業倒閉

我們對待這兩種類型的服務器端驗證的相同方式當任何請求未通過任何驗證時,我們會發回一個帶有包含詳細錯誤消息的json對象的HTTP 400,說明它爲什麼失敗。樣本響應將是

HTTP 400 Bad Request 
{ 
     "bsb_name" :"bsb_name has special characters",   
     "bsb_number":"bsb number doesn't exist", 
     "amount":"amount is required" 
} 

現在的問題是,我們是不是誰都能當我們使用asp.net框架加OWIN框架返回HTTP 400的唯一政黨,框架本身也可以發送回HTTP 400在某些情況下,他們發送的HTTP 400與我們完全不同。這爲前端創建額外的工作來區分兩種類型的HTTP 400並以不同的方式處理它們。

提出了一項提案,以重新的因素我們的反應和,而不是發送回JSON對象,我們發回普通字符串---基於的假設是asp.net框架/ owin會以純送回他們的HTTP 400字符串(1)。所以在前端我們沒有區分它們,並且可以以相同的方式處理它們。此外,爲避免引入魔術分隔符,我們只返回第一條錯誤消息文本,而不是全部。因此,一個樣本響應可能是

HTTP 400 Bad Request 
"Bank account name has special characters" 

,我們會以同樣的方式來對待它由ASP返回一個HTTP 400。網框架,比方說,

HTTP 400 Bad Request 
Request header too long 

因此,在這兩種情況下,一個網站的用戶將提交自己的形式說:「銀行的帳戶名具有特殊字符」或「請求頭太長」

後看到一個錯誤信息解決方案 2:使用業務協議而不是HTTP協議

如果請求失敗的基本服務器端驗證,這隻能發生在黑客,服務器將立即拋出異常,最終將HTTP 500.一旦收到HTTP 500 ,客戶端會簡單地將用戶引導至一個gen口頭錯誤頁面說沒有任何詳細信息意外發生 - 我們儘量避免被黑客友好。

如果請求未通過高級服務器端驗證,這可能會發生在普通應用程序用戶身上,但服務器仍然會返回HTTP 200-成功,但具有不同的status_code表示這是錯誤響應。例如

HTTP 200 Success 
    { 
     status_code: Err_123 
     error_message: "bsb doesn't exist" 
    } 

我個人想用解決方案2,但被告知我們不應該使用HTTP 200來驗證錯誤。由於HTTP 200代表OK,所以在服務器端驗證失敗的情況下使用HTTP 200是沒有意義的。

我的理解是,HTTP狀態碼是爲HTTP協議而設計的,應該與您的業務邏輯無關。 HTTP 200僅表示客戶端已將請求發送到服務器,並且服務器已成功處理它返回響應。響應是指交易已被批准,或交易已被拒絕,或者您提交的BSB_Number不存在,它根本不在意。它不應該在意。

所以在事務被拒絕的情況下,或者表單有一些只能在服務器端檢測到的無效輸入時,我們仍然應該響應HTTP 200,但分配一個不同的status_code,這相當於HTTP 400 ,但是,這是在我們的商業協議。如此有效,我們應該將我們的業務協議與http協議分開,並且我們不能使用HTTP FAILURE來代表商業失敗(2)。

以上是我對此的全部想法,我歡迎所有意見,對此主題進一步討論。

乾杯, 博

  • (1):假設是錯誤的,因爲我最近發現IIS可以在某些情況下返回HTTP 400。當發生這種情況時,它會返回一個HTML頁面。

  • (2):一個比喻可能是

**IP -- TCP -- HTTP -- BUSINESS** If TCP layer fails, IP shouldn't be concerned; If HTTP layer fails, TCP shouldn't be concerned; If BUSINESS layer fails, HTTP shouldn't be concerned;

不是 '單獨關注的' 編程常識?當看到有人說「在出現業務故障的情況下返回HTTP 400是可以的」時,我有點驚訝。

+0

個人而言,我認爲你應該使用的商業協議。 HTTP協議錯誤表明,當這不是產生異常的時候。 – rolls

+0

https://www.iis.net/learn/troubleshoot/diagnosing-http-errors/troubleshooting-http-400-errors-in-iis –

回答

2

關注點的分離首先應該是我的看法。

解決方案一,儘管陳述錯誤源於業務層,但意味着演示文稿存在錯誤。現在對於錯誤實際發生的位置是不明確的。

另一方面,解決方案2詳細說明HTTP事務成功並且業務邏輯響應錯誤。

理想情況下(在我看來)服務器端的所有錯誤都應該被捕獲並報告爲業務邏輯中的錯誤,這樣唯一引發HTTP錯誤的時間是用戶請求不良或敏感頁面時。

這會導致系統更優雅地失敗,並使其更具可擴展性。 (如果你在其他地方實現你的API,你不需要在其中包含HTTP錯誤處理,只需要顯示所述錯誤)

另外,這可能更適合P.SE,而不是所以。

+2

這是一個很好的答案,因爲它使在不同的協議和設備解決方案便攜。雖然您現在可能總是使用HTTP,但將來可能並非如此。即使你從未打算從HTTP移動,這純粹是因爲它明顯區分了HTTP異常和業務邏輯異常,這是一個很好的答案。 – rolls

0

我的解決方案與解決方案2類似。我將一個實體定義爲所有RESTful請求的響應。

class Entity<T>{ 
    public int code {get;set;} 
    public int message {get;set;} 
    public T content {get;set;} 
} 

無論請求成功還是失敗,前臺都會得到一個實體並檢查代碼。如果代碼是200(或其他定義的),則繼續處理內容,否則顯示消息並返回。

0

對於來自正常渠道的請求,它永遠不會失敗,如果確實如此,那就意味着我們正在處理黑客。

如果你的API是公開的,爲什麼不使用狀態碼500,...這是欺騙人們嘗試訪問你的API的方法。但是,你現在如果這不是內部服務器錯誤與讀取狀態消息。或you use Status Code 202(該請求已被接受處理,但處理尚未完成,該請求可能最終也可能不會被執行,因爲在處理實際發生時可能不允許該請求,也不存在異步狀態返回的設施操作本等。)

如果使用狀態碼200或400,和每一個身體知道是否可以注射......可是,你的,這只是我的建議像你需要什麼意見。

0

在我看來你的400響應碼是好的。你實際上需要建模你應該如何迴應驗證場景。例如,一個BaseResponse.cs看起來像這樣。

public class BaseResponse<T> where T: object { 
    public T Data {get;set;} 
    public bool Success {get; set;} 
    public IList<Error> Errors {get;set;} 
} 

在另一方面作爲反應應用的Javascript端遵循

public class Error { 
    string Type {get;set;} // "validation", "business" 
    string Code {get;set;} // "VAL_1234", "BIZ_4321" 
    string Message {get;set;} // "Value should be greater than 10" 
} 

現在你可以定義錯誤類代碼並不複雜

fetch(url) 
.then((response)=> { 
    if(response.status === 400) { 
    let json = response.json(); 
    if(json) { // you have validation errors, do something with errors property in json 
    }else { // 400 was returned because of some other reason 
    } 
    } 
}); 

更參與解決方案與我上面的工作一起工作。樣品here

+0

你讓json = response.json()會拋出異常時 https://www.iis.net/learn/troubleshoot/diagnosing-http-errors/troubleshooting-http-400-errors-in-iis –

+0

我的代碼僅用於說明目的。對於例外情況,您可以採取不同的處理方式。基本上需要檢查響應是否具有正文。 – Perpetualcoder

+0

HTTP 400可以來自您的虛擬主機(i..e IIS,apache或Nginx),可以來自web框架(asp.net,f​​lusk,rails ..),也可以來自您的代碼。 有沒有辦法知道它來自你不知道IIS,Apache的,Nginx的,asp.net,f​​lusk,軌道格式的HTTP 400 爲什麼我們需要區分它們,是因爲我們可以處理的原因我們的後端代碼優雅地返回錯誤,因爲我們知道它是什麼;但我不知道如何處理由IIS返回的HTT 400,例如,如果它發生,我們只能讓它進入常規錯誤頁面。 –

相關問題