我们正在构建一个Web应用程序,我们在前端显示服务器端验证错误消息时遇到了一些问题.
为了给出一些上下文,我们运行一个单页面应用程序,其中前端在asp.net中的react.js和backend 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"
}
现在问题是,我们不是唯一可以返回HTTP 400的一方.由于我们使用的是asp.net框架加上OWIN框架,框架本身也可以在某种情况下发回HTTP 400,并且他们发送的HTTP 400是与我们截然不同.这为前端创建了额外的工作,以区分两种类型的HTTP 400并以不同的方式处理它们.
我们建议重新考虑我们的响应,而不是发送回JSON对象,我们发送回普通字符串—基于asp.net framework / owin将以纯字符串(1)发回HTTP 400的假设.所以在前端我们没有区分它们并且可以以相同的方式处理它们.此外,为了避免引入魔术分隔符,我们只返回第一个错误消息文本而不是所有文本.所以样本响应可能是
HTTP 400 Bad Request
"Bank account name has special characters"
我们将以与asp.net框架返回的HTTP 400相同的方式对待它,比方说,
HTTP 400 Bad Request
Request header too long
因此,在这两种情况下,站点用户在提交表单“银行帐户名称具有特殊字符”或“请求标题太长”后会看到错误消息
解决方案2:使用业务协议而非HTTP协议
如果请求未通过基本服务器端验证(这只会发生在黑客身上),服务器会立即抛出异常,最终会出现HTTP 500.一旦收到HTTP 500,客户端就会直接将用户引导到一般错误页面意外发生没有任何详细信息 – 我们试图避免黑客友好.
如果请求未通过高级服务器端验证(这可能发生在正常的应用程序用户身上),服务器仍将返回HTTP 200 – Success,但使用不同的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 – 业务**
如果TCP层出现故障,则不应关注IP;
如果HTTP层失败,则不应关注TCP;
如果业务层失败,则不应关注HTTP;
编程中的常识不是“关注点”吗?当看到有人说“在业务失败的情况下可以返回HTTP 400时,我有点惊讶”
最佳答案 在我看来,关注点的分离应该是首要的.
解决方案一,虽然说明错误源自业务层,但意味着表示有错.现在,关于错误实际来源的位置是模棱两可的.
另一方面,解决方案2详细说明HTTP事务是成功的,并且业务逻辑响应错误.
理想情况下(在我看来)服务器端的所有错误都应该被捕获并报告为业务逻辑中的错误,因此,只有当用户请求错误或敏感页面时,才会抛出HTTP错误.
这会导致系统更优雅地失败,并使其更具可扩展性. (例如,如果您在其他地方实现了API,则不需要在其中包含HTTP错误处理,只显示所述错误)
顺便说一下,这可能更适合P.SE而不是SO.