当前位置 : 主页 > 网页制作 > Nodejs >

node.js – 清理从客户端传递到req.body和标头上的api后端的数据

来源:互联网 收集:自由互联 发布时间:2021-06-16
我有一个带有onSubmit函数的表单从状态收集输入数据并将其发送到后端. 然后我收集来自req.body的输入和来自后端头部的ip. ip被持久化为redis,表单输入通过pm2传递给另一个守护进程,最后用
我有一个带有onSubmit函数的表单从状态收集输入数据并将其发送到后端.

然后我收集来自req.body的输入和来自后端头部的ip.

ip被持久化为redis,表单输入通过pm2传递给另一个守护进程,最后用mandrill邮寄,而不是持久保存到任何数据库.

情景一

收集客户端IP并将其保留为redis:

module.exports = (req, res, next) => {
  const client = redis.createClient()
  client.select(2, (err) => {
    console.log('redisWriteIP selected 2snd redis db')
    if (err) {
      next(new DbErr(err))
    } else {
      const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
      client.set(ip, true, 'EX', 120, (err, rep) => {
        if (err) {
          next(new DbErr(err))
        } else {
          return next()
        }
      })
    }
  })
}

问题1:
在这种情况下,我是否需要清理ip?用户可以使用请求标头发脾气并发送除了他的IP地址或号码之外的任何其他内容吗?

情景2

输入字段由用户填写并发送到req.body上的api

api服务器 – 使用body解析器:

const api = express()

// Body parser for the post requests
const bodyParser = require('body-parser')
api.use(bodyParser.urlencoded({ extended: false }))
api.use(bodyParser.json())
api.set('trust proxy', 'loopback')

const routes = require('./routes')
api.use('/api', routes)

验证字段middlware:

module.exports = (req, res, next) => {
      let payload = req.body
      const err = {}
      let isFormValid = true
      // Validating a form.
      if (payload.question) {
        if (typeof payload.email !== 'string' || !validator.isEmail(payload.email)) {
          isFormValid = false
          err.email = 'Please provide a correct email address.'
        }
        if (typeof payload.name !== 'string' || payload.name.trim().length === 0) {
          isFormValid = false
          err.name = 'Please provide your name.'
        }
      // Validating another form.
      } else if (payload.booking) {
        if (typeof payload.email !== 'string' || !validator.isEmail(payload.email)) {
          isFormValid = false
          err.email = 'Please provide a correct email address.'
        }
        if (typeof payload.dates !== 'string' || payload.dates.trim().length === 0) {
          isFormValid = false
          err.msg = 'Something went wrong'
        }
      } else {
        // No form type in the payload.
        isFormValid = false
        err.msg = 'Something went wrong'
      }
      if (!isFormValid) {
        next(new FormFieldErr(JSON.stringify(err)))
      } else {
        return next()
      }
    }

数据如何发送到另一个进程的示例:

...
 // Send the payload to the mandrill pid.
      pm2.sendDataToProcessId(pid, payload, (err, res) => {
        if (err) {
          next(new MailerErr(err))
        } else {
          next()
        }
      })

问题2:
在对数据进行任何类型的操作之前,我是否需要清理req.body,即使它没有持久存储到任何数据库.
例如,在我检查验证中间件中是否(payload.question){…}之前,还是在使用pm2.sendDataToProcessId方法发送有效负载之前?
我担心即使没有数据持久存在,也可以从客户端传递函数并在后端执行.

问题3
如果以上确实存在安全风险,我可以简单地在req.body上的链的开头运行一个middlware,以及我可能使用的请求的任何其他部分,转义或删除所有危险字符并有效地解决问题吗?

编辑

我见过验证字段的库,但我不需要广泛的验证解决方案,而是一个简单的卫生解决方案.这就是为什么我想要制作或安装一个中间件,它首先保存req.body或任何其他没有危险字符的数据,然后其他middlwares可以安全地处理数据.
就像是:

清理中间件:

module.exports = (req, res, next) => {
  req.body.replace(/[|&;$%@"<>()+,]/g, "")

  return next()
}

一些api路线:

api.route('/', sanitise, someMiddleware, (req, res, next) => {
  // Now we can safely handle req.body in the middlwares.
})
答案1:是的,用户可以更改任何标题.但不是req.connection.remoteAddress.所以你可能想优先考虑那个.

答案2:是的,逃避字符串和验证数据组合通常是一种很好的做法.您应该在API级别执行此操作.

答案3:我喜欢Joi作为一个很好的API验证包.还有其他套餐可能更适合您的需求.

网友评论