【发布时间】: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.
})
【问题讨论】:
-
您的问题得到答复了吗?