清理从客户端传递给req.body和头部的api后端的数据

我有一个表单,onSubmit函数从状态收集input数据并将其发送到后端。

然后我从后端收集来自req.body和ip的input。

IP持久化到redis,表单input通过pm2传递给另一个守护进程,最后用mandrill邮寄,而不是持久化到任何数据库。

情景I

客户端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

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

api服务器 – 使用bodyparsing器:

 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) 

validation字段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,即使它没有保存到任何数据库。 例如,在我检查validation中间件中的if (payload.question) {...}之前,还是在使用pm2.sendDataToProcessId方法发送有效内容之前? 我担心一个函数可以从客户端传递,并在后端执行,即使没有数据持久。

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

编辑

我已经看过validation字段的库,但是我不需要广泛的validation解决scheme,而是一个简单的卫生解决scheme。 这就是为什么我想要制作或安装一个中间件,它会首先保存请求者或任何其他没有危险字符的数据,然后其他中间件可以安全地处理数据。 就像是:

消毒中间件:

 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:是的,转义string和validation数据组合通常是一个好习惯。 您应该在API级别执行此操作。

答案3:我喜欢Joi作为一个很好的APIvalidation包。 还有其他的包可能更适合你的需求。