【问题标题】:where to validate user input on the server side?在哪里验证服务器端的用户输入?
【发布时间】:2014-10-17 14:17:52
【问题描述】:

我了解在 Web 开发中,用户输入应在客户端和服务器端进行验证。

我很难弄清楚在服务器端验证输入的位置。
例如,在请求通过中间件并到达控制器之后。在控制器中,我有其他模块将接受输入并最终到达目的地然后响应。

是否应该在控制器中完全验证输入,以便在将输入放入其他模块时按预期进行?或者我应该检查接受输入的模块中的输入?或者我应该对控制器中的输入进行“浅层”检查(基本的原始类型检查等)并在模块本身中保留业务逻辑检查(值是​​正数吗?负数?等)?

示例代码:
控制器.js

  var mashUp = require('./mashupService');

  var create = function(req, res) {
  var user = req.body.user;
  var imageName = req.body.imageName;
  var description = req.body.description;

  //more validation here? 

  if (!user) {
    return ApiResponse(req, res, new Error('no user'));
  } else if (!imageName) {
    return ApiResponse(req, res, new Error('no image name'));
  } else if (!description) {
    return ApiResponse(req, res, new Error('no description'));
  }

  // continue with business
  mashUp(user, imageName, description, function(err, id) {
    if (err) {
      return ApiResponse(req, res, new Error('mashup error'));
    }
    return ApiResponse(req, res, { id: id });
  }); 
};

`其他模块、库等'

var User = require('./model/user');


function mashUp(user, imageName, desc, callback) {

  //more validation here?

  User.find({ user: user }, function(err, _user) {
    //do stuff


    callback(err, id) ;
  });
}

module.exports = mashUp

【问题讨论】:

  • 您没有在客户端上进行验证。这可能很好,但不是绝对必要的。

标签: javascript node.js validation


【解决方案1】:

嗯,当您从不同的角度验证数据时会有所不同:

模型验证: 当您有一条规则需要应用于您的数据模型时,例如 required、min、max、match 等。如果在大多数情况下任何验证失败,这些规则将使用任何 orm 或 odm 构建成 int,这将冒泡到中间件你可以从那里处理。

如果您需要实现更复杂的逻辑,您可以选择设置自定义验证器。

这是一个月光示例:

var UserSchema = new Schema({
    firstName: {
        type: String,
        trim: true,
        default: '',
        validate: [customValidator, 'Please fill in your first name'] 
        // custom validator
    },
    lastName: {
        type: String,
        trim: true,
        default: '',
        validate: [customValidator, 'Please fill in your last name']
        // custom validator
    },
    displayName: {
        type: String,
        trim: true
    },
    email: {
        type: String,
        trim: true,
        unique: true,
        default: '',
        validate: [customValidator, 'Please fill in your email'], 
        // custom validator
        match: [/.+\@.+\..+/, 'Please fill a valid email address'] 
        //match validator
    },
    username: {
        type: String,
        unique: true,
        required: 'Please fill in a username', //required validator
        trim: true
    }
});

更多参考请查看mongoose 验证

业务规则

这更适用于您现在描述的场景,处理可能适用于系统中特定情况或用户历史的规则。

我不建议在控制器中管理验证,竖起大拇指的规则是创建胖模型和瘦控制器,你可以用谷歌搜索,但我随机选择了这个presentation 和这个article

据说我更喜欢在控制器执行之前在中间件中进行这些验证。

让我们为下面的案例做一个案例

在编辑文章时,让我们验证 id 是否属于该用户 正在请求编辑

exports.validateArticle = function(req, res, next){
 var userId = req.param('userId'),
     articleId = req.param('articleId');

    // TODO: logic validation
}

然后你在控制器执行之前连接你的中间件,比如

app.route('/article').all( rule.validateArticle ).post(controller.editArticle);

这样你就不会用一堆验证来污染你的控制器,你也可以在一个控制器之间重复使用验证。

作为旁注,客户端验证是为了用户体验而进行的,但不依赖于它们作为您系统的适当验证器。

这里只有我的两分钱, 我希望这会有所帮助。

干杯!

【讨论】:

  • +1 用于参考。我喜欢在中间件中进行一些验证并能够在整个过程中重用它们的想法。但是不同的 API 会有大部分不同的输入,其中有一些类似的用户 ID 等。我可以看到一种验证类型检查所有常见输入并为每个特定 API 使用不同的中间件验证。这看起来像是一种“三明治”验证方法,其中中间件和模型负责边界,控制器是接口。
  • 最后,这些模型验证被传递给一个中间件,你也可以处理它们,因为你提到一个常见的场景可能是你必须为每个 API 验证不同的输入,但是在方案可以帮助您使用单个入口点来验证特定属性,并避免在您需要验证的所有控制器中每次需要它时创建验证,另一方面,业务规则更具体到您的域并绑定到您的用户历史记录,就我而言,为了简单起见,我有一个模型和中间件文件夹
【解决方案2】:

这是关于数据验证的。 由于客户端数据通常不可靠,因此无需在客户端进行数据验证。必须在服务器上验证正确的数据。我建议您在控制器而不是其他模块中进行验证。让我们看看你的例子:

  var create = function(req, res) {
  var user = req.body.user;
  var imageName = req.body.imageName;
  var description = req.body.description;

  //more validation here? 

回答:是的。考虑用户是否存在或拥有 权限,描述至少有10个字符,包含非法字符等。

  if (!user) {
    return ApiResponse(req, res, new Error('no user'));
  } else if (!imageName) {
    return ApiResponse(req, res, new Error('no image name'));
  } else if (!description) {
    return ApiResponse(req, res, new Error('no description'));
  }
//Btw, here is kind of validation right? 
//but it looks like that you only want to check if user is posted, 
//then imageName and description will be ignored. 
//There may be some logic error here.

最后,我还建议您创建一个专门用于数据验证的模块。

【讨论】:

  • 感谢您的提示。客户数据不可信。重要和最关键的验证在服务器上。这就是我主要担心的地方。我知道我需要进行许多检查(类型检查、存在和规则),但我不太确定将这些检查放在哪里。中间件、控制器和模型。多少验证放在哪里?
  • 正如我所建议的,最好有一个专门处理数据验证的模块。你可以看看github.com/chriso/validator.js。关于放置位置,检查,我会在控制器中进行以减少模型中的麻烦工作
猜你喜欢
  • 1970-01-01
  • 2021-12-13
  • 2017-05-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-05
  • 2010-09-06
  • 1970-01-01
相关资源
最近更新 更多