如何在服务器端最好地验证JSON

sky*_*ork 18 security api validation json web-services

在服务器端处理POST,PUT和PATCH请求时,我们经常需要处理一些JSON来执行请求.

很明显,我们需要以某种方式验证这些JSON(例如结构,允许/预期键和值类型),我至少可以看到两种方式:

  1. 收到JSON后,在对JSON进行任何操作以完成请求之前,先按原样验证JSON.

  2. 按原样获取JSON,开始处理它(例如访问其各种键值)并尝试在执行业务逻辑时随时验证它,并可能使用一些异常处理来处理时态数据.

第一种方法与第二种方法相比似乎更加强大,但可能更昂贵(时间成本),因为每个请求都将得到验证(并且希望它们中的大多数都是有效的,因此验证有点多余).

第二种方法可以保存对有效请求的强制验证,但是在业务逻辑中混合检查可能是错误的甚至是有风险的.

以上哪两个更好?或者,还有更好的方法吗?

jth*_*_92 10

您使用POST,PUT和PATCH描述的内容听起来就像是在实现REST API.根据您的后端平台,您可以使用将JSON映射到非常强大的对象并为您执行验证的库.在JAVA中,您可以使用Jersey,SpringJackson.如果您使用的是.NET,则可以使用Json.NET.

如果效率是您的目标,并且您希望验证每个请求,那么如果您使用JavaScript可以使用json2.js,那么在前端进行评估将是理想的.

关于比较您的方法,这是一个Pro/Cons列表.

方法#1:根据要求

优点

  1. 保持业务逻辑完整性.正如您所提到的,在处理业务逻辑时尝试验证可能会导致实际上无效的无效测试,反之亦然,或者验证可能会无意中对业务逻辑产生负面影响.
  2. 正如诺伯特所提到的,事先捕捉错误将提高效率.这个逻辑问题是为什么要花时间处理,如果首先出现错误?
  3. 代码将更清晰,更易于阅读.将验证和业务逻辑分开将使代码更清晰,更易于阅读和维护.

缺点

  1. 它可能导致冗余处理意味着更长的计算时间.

方法#2:在Go上进行验证

优点

  1. 从理论上讲,通过保存过程和计算时间来实现它们是有效的.

缺点

  1. 实际上,节省的处理时间可能微不足道(如Norbert所述).无论哪种方式,您仍在进行验证检查.此外,如果发现错误,则浪费处理时间.
  2. 可以包括数据完整性.在以这种方式处理时,JSON可能会损坏.
  3. 代码不是很清楚.在阅读业务逻辑时,可能不会发生什么事情,因为验证逻辑是混合的.

它真正归结为Accuracy vs Speed.它们通常具有反比关系.随着您变得更加准确并验证您的JSON,您可能不得不在速度上妥协.这在大型数据集中确实很明显,因为这些天计算机真的很快.由于您在接收数据时对数据的准确程度或者额外的一秒左右是否至关重要,因此您需要决定哪些更重要.在某些情况下,它确实很重要(即与股票市场和医疗保健应用程序,毫秒重要),两者都非常重要.在这种情况下,当您增加一个,例如准确度时,您可能必须通过获得更高性能的机器来提高速度.

希望这可以帮助.


Nor*_*len 6

第一种方法更加强大,但不一定非常昂贵.即使您因错误而中止解析过程,它也会变得更便宜:您的业务逻辑通常占用流程中90%以上的资源,因此如果您的错误百分比为10%,那么您已经是资源中立的.如果您优化验证过程以便预先执行业务流程的验证,那么您的错误率可能会低得多(例如,20比1中的1比1)以保持资源中立.

有关假设前期数据验证的实现的示例,请查看GSON(https://code.google.com/p/google-gson/):

GSON的工作原理如下:JSON的每个部分都可以转换为对象.此对象是类型化的或包含类型化数据:示例对象(用作示例语言的JAVA):

public class someInnerDataFromJSON {
    String name;
    String address;
    int housenumber;
    String buildingType;
    // Getters and setters
    public String getName() { return name; }
    public void setName(String name) { this.name=name; }
    //etc.
}
Run Code Online (Sandbox Code Playgroud)

GSON解析的数据是使用提供的模型,已经进行了类型检查.这是您的代码可以中止的第一个点.

在此出口点之后,假设数据已确认到模型,您可以验证数据是否在特定限制范围内.您也可以将其写入模型中.

假设这个buildingType是一个列表:

  • 单身家庭的房子
  • 多家庭的房子
  • 公寓

您可以通过创建检查数据的setter来检查解析期间的数据,也可以在第一组业务规则应用程序中解析后检查数据.首先检查数据的好处是,您的后续代码将具有较少的异常处理,因此更少且更容易理解代码.