2016-10-21 68 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,例如,如果它发生,我们只能让它进入常规错误页面。 –

相关问题