ExpressJS 设置 JSON 解析的深度

ExpressJS set the Depth of JSON Parsing

我想在 Express 中间件 express.json() 中设置 JSON 解析的深度

例如,如果我将选项设置为解析 depth=1,则

'{ "email": { "$ne": "user@example.com" } }'

将被解析为

{ email: "[object Object]" }

-- 或--

当我设置depth=2,那么

'{ "email": { "$ne": "user@example.com" } }'

将被解析为

{ email: { '$ne': 'user@example.com' } }

以此类推,

在这种情况下,不会有默认深度的问题,因为开发人员会在开发时知道他们允许多少嵌套。

PS:它将防止应用程序受到 NoSQL 注入的攻击。

我写下查询,最多6-8个深度。在查找中使用查找时。

  const [result] = await Collection.aggregate([
    { $match:statusObj },
     {
         $project:{
             _id:1,
             name:1
             }
     },
     {
      $lookup:{
           from:"articles",
            let: { "cat_id":"$_id"},
            pipeline:[
             {
                $match:{
                     $expr:{
                  $and: [
                         { $eq: ["$category_id", "$$cat_id"] }, 
                         { $eq: ["$isDeleted", false] },
                         { $eq: ["$type", type] }
                         ]
                     }

                    } 
                 },
                  {
      $lookup:{
           from:"view_articles",
            let: { "article_id":"$_id"},
            pipeline:[
             {
                $match:{
                     $expr:{
                  $and: [
                         { $eq: ["$article_id", "$$article_id"] }, 
                         { $eq: ["$isDeleted", false] }
                         ]
                     }

                    } 
                 }
                 ],
                 as:"viewCount"
          }    
    },
    {
      $addFields:{
          noOfViewCount : { $size:"$viewCount"}
          }   
      }          ],
                 as:"articleCategoryData"
          }    
    },
     {
      $addFields: {
      postCount: {$size:"$articleCategoryData"   },
      tempsArray: { $map:
        {
           input: "$articleCategoryData",
           as: "tempData",
           in: { $add: "$$tempData.noOfViewCount" }
        }
     },
                 },
      },
      {
        $addFields: {
          viewCount:{ $sum:"$tempsArray" }
              },
        },
        {
          $project:{
            _id: 1,
            name: 1,
            postCount: 1,
            viewCount: 1
              }
      },
      {
        $facet: {
          count: [
            {
              $count: "total"
            }
          ],
          result: [{ $match: {} }, { $skip: skipRecord }, { $limit: limit }]
        }
      }
]);

您可以将深度设置为 10。如果您觉得 JSON 不对,请增加它:)

只写你自己的middleware:

const get_depth = (obj) => {
    let depth = 0
    for(const key in obj) {
        if( obj[key] instanceof Object ) {
          depth = Math.max(get_depth(obj[key]), depth)
        }
    }
    return depth+1
}
const depth_limit = 2
const limit_depth = function(req, res, next) {
    if( get_depth(req.body) > depth_limit ) throw new Error("Possible NoSQL Injection")
    next()
}

app.use(limit_depth)

或者,如果您更喜欢 "[object Object]"

let limit_depth = (obj, current_depth, limit) => {
    for(const key in obj) {
        if( obj[key] instanceof Object ) {
          if( current_depth+1 === limit ) {
            obj[key] = "[object Object]" // or something similar
          }
          else limit_depth(obj[key], current_depth+1, limit)
        }
    }
}
app.use(function(req, res, next) { limit_depth(req.body, 0, depth_limit); next() })

如果不想更改 req.body 的值,可以使用 here

中的此功能
function serializer(payload: any, cdepth: number, options: Options): void {
  const main: any = {}
  const maxDepth = typeof options.maxNestingLevel == 'number' ? (options.maxNestingLevel == 0 ? 1 : options.maxNestingLevel) : 1

  for (const key in payload) {
    // check for object
    if (payload[key] instanceof Object) {
      // check if depth is limited, replace if needed
      if (cdepth === maxDepth) {
        main[key] = options.replaceWith
      } else {
        // serialize the nested
        main[key] = serializer(payload[key], cdepth + 1, options)
      }
    } else {
      // add to main object if not to be checked
      main[key] = payload[key]
    }
  }
  return main
}