我正在从客户端向我的服务器发送一个包含用户信息的对象:
const newUserData = {
name,
username,
gender,
avatar,
}
我害怕一个";坏用户";,试图破解我的系统修改客户端像这样:
const newUserData = {
name, // I validate type and format in the server
username, // I validate type and format in the server
gender, // I validate type and format in the server
avatar, // I validate type and format in the server
totalFollowers: 4022348978890, <------- Unexpected field on the server side...
premium: true <------- Unexpected field on the server side...
}
然后,如果我在服务器中获得这个对象并更新数据库,该用户将是著名的和高级的。
在服务器端,我只期望字段";name"用户名"性别";,以及";化身";。
如果对象"newUserData";有其他意想不到的领域吗?
注意:我正在寻找一种通用的方法,因为黑客可以在客户端添加他/她想要的字段。
无论用户通过编辑api请求参数发送数据,只要您只访问和针对特定属性,这些参数在服务器端不会有任何区别。例如,如果我只想要服务器上的用户名、电子邮件或密码,那么显然我只会从API请求参数中获得这3个值,而不关心其他参数。我可能会编辑请求并添加100个其他参数,这些参数只会发送到服务器,但由于您只访问请求对象中的3个值,因此所有其他参数都将被忽略。不过,不需要实现复杂的逻辑,您可以使用以下简单的伪代码逻辑。
const allowed_params = ['username','email','password']
foreach(param in request.params){
if(param in allowed_params){
//this is only that is allowed
}else{
//just ignore this
}
您可以检查密钥是否相等:
function compareKeys(a, b) {
var requiredKeys = Object.keys(a).sort();
var receivedKeys = Object.keys(b).sort();
return JSON.stringify(requiredKeys) === JSON.stringify(receivedKeys);
}
根据您在服务器端所做的操作,您可以执行:
- 显式地破坏request.body,并将每个属性传递给下一个函数(数据库更新等(
- 使用诸如mongoose或Sequelize之类的ORM库-它们会丢弃意外的字段
一种相对简单的方法如下:
// defining a function with Arrow syntax, into which two
// arguments are passed:
// submittedObject: the Object supplied by the user,
// permittedFields: an Array of permitted Object keys:
const expectedFieldsOnly = (submittedObject, permittedFields = []) => {
// here we use Object.keys() to retrieve an Array of
// the submitted Object's keys:
const haystack = Object.keys(submittedObject),
// we then use Array.prototype.filter() to iterate
// through the Array of permitted Object keys:
filtered = haystack.filter(
// we use an anonymous Arrow function to assess
// the keys; if the current key of the Array of
// submitted Objects keys is not found in the
// Array of permitted keys we retain that key
// in the Array:
(key) => permittedFields.indexOf(key) == -1
);
// here we return an Object containing
// matchesExpectations: a property containing
// a Boolean; true if the Object had only
// expected keys, and false if extra keys were
// found:
return {
matchesExpectations: filtered.length === 0,
// an Array of the unexpected keys, to be used in
// the event of Error messages being returned or
// logged:
unexpectedKeys: filtered,
}
},
// an Array of expected keys:
permitted = ['name', 'username', 'gender', 'avatar'],
// 'good'/'normal' submission:
submission1 = {
name: "James",
username: "justAGuy",
gender: "m",
avatar: "probably",
},
// 'bad'/'abnormal' submission:
submission2 = {
name: "James",
username: "somebody",
gender: "f",
avatar: "maybe",
totalFollowers: 4022348978890,
premium: true
}
console.log(expectedFieldsOnly(submission1, permitted));
console.log(expectedFieldsOnly(submission2, permitted));
参考文献:
- 箭头函数
- CCD_ 1
- CCD_ 2
Object.keys()