我正在使用Node.js,Mongoose和Koa开发RESTful API,并且对于模式和输入验证的最佳实践有些困惑。
目前,我对每种资源都有Mongoose和Joi模式。猫鼬模式仅包含有关特定资源的基本信息。示例:
const UserSchema = new mongoose.Schema({
email: {
type: String,
lowercase: true,
},
firstName: String,
lastName: String,
phone: String,
city: String,
state: String,
country: String,
});
Joi模式包含有关对象的每个属性的详细信息:
{
email: Joi.string().email().required(),
firstName: Joi.string().min(2).max(50).required(),
lastName: Joi.string().min(2).max(50).required(),
phone: Joi.string().min(2).max(50).required(),
city: Joi.string().min(2).max(50).required(),
state: Joi.string().min(2).max(50).required(),
country: Joi.string().min(2).max(50).required(),
}
当写入数据库时,Mongoose模式用于在端点处理程序级别创建给定资源的新实例。
router.post('/', validate, routeHandler(async (ctx) => {
const userObj = new User(ctx.request.body);
const user = await userObj.save();
ctx.send(201, {
success: true,
user,
});
}));
Joi模式在验证中间件中用于验证用户输入。对于每种资源,我有3种不同的Joi模式,因为允许的输入取决于请求方法(POST,PUT,PATCH)而有所不同。
async function validate(ctx, next) {
const user = ctx.request.body;
const { method } = ctx.request;
const schema = schemas[method];
const { error } = Joi.validate(user, schema);
if (error) {
ctx.send(400, {
success: false,
error: 'Bad request',
message: error.details[0].message,
});
} else {
await next();
}
}
我想知道我目前在Mongoose之上使用多个Joi模式的方法是否最佳,因为Mongoose也具有内置的验证功能。如果没有,应该遵循哪些良好做法?
谢谢!
答案 0 :(得分:1)
即使您拥有猫鼬模式,实现验证服务也是一种常见的做法。如您所说,在对数据执行任何登录之前,它将返回验证错误。因此,在这种情况下,肯定会节省一些时间。 而且,您可以通过joi获得更好的验证控制。但是,它也很大程度上取决于您的要求,因为它会增加您必须编写的额外代码,可以避免这些代码,而不会对最终结果造成太大影响。
答案 1 :(得分:0)
尽管出于安全目的而进行了客户端验证,以保护服务器免受恶意用户的侵害,但最好进行服务器端验证。
JOI was available for server-side validation but now it's deprecated so better to use express-validator.
答案 2 :(得分:0)
IMO,我认为这个问题没有明确的答案。就像@omer 在上面的评论部分所说的那样,Mongoose 足够强大,可以站稳脚跟。
但是,如果您的代码在接收输入后的逻辑/操作非常繁重且成本高昂,那么在 API 层添加额外的保护以防止繁重的代码运行也无济于事。
编辑:我刚刚从一位受人尊敬的人那里发现了这个好answer。