【问题标题】:Sanitising data passed from the client to the api backend on the req.body and the headers在 req.body 和 headers 上清理从客户端传递到 api 后端的数据
【发布时间】:2017-09-06 04:29:29
【问题描述】:

我有一个带有 onSubmit 函数的表单,它从状态中收集输入数据并将其发送到后端。

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

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

场景一

客户端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 服务器 - 使用正文解析器:

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)

验证字段中间件:

 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 进行清理,即使它没有保存到任何数据库。 例如,在我在验证中间件中检查if (payload.question) {...} 之前,或者在我使用pm2.sendDataToProcessId 方法发送有效负载之前? 我担心即使没有数据持久化,也可以从客户端传递一个函数并在后端执行。

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

编辑

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

清理中间件:

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.
})

【问题讨论】:

  • 您的问题得到答复了吗?

标签: node.js reactjs


【解决方案1】:

答案 1: 是的,用户可以更改任何标题。但不是req.connection.remoteAddress。所以你可能想优先考虑那个。

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

答案 3: 我喜欢 Joi 作为一个不错的 API 验证包。还有其他软件包可能更适合您的需求。

【讨论】:

    猜你喜欢
    • 2021-12-29
    • 2017-04-02
    • 1970-01-01
    • 1970-01-01
    • 2016-09-29
    • 1970-01-01
    • 2018-11-02
    • 2020-07-10
    • 1970-01-01
    相关资源
    最近更新 更多