컬렉션을 채울 때 쿼리에서 반환되지 않도록 Mongoose / MongoDB의 암호 필드를 보호하는 방법은 무엇입니까?
두 개의 컬렉션 / 스키마가 있다고 가정합니다. 하나는 사용자 이름 및 비밀번호 필드가있는 사용자 스키마이고, 작성자 필드에 사용자 스키마에 대한 참조가있는 블로그 스키마가 있습니다. Mongoose를 사용하여 다음과 같은 작업을 수행하면
Blogs.findOne({...}).populate("user").exec()
블로그 문서와 사용자도 입력하게되지만 Mongoose / MongoDB가 비밀번호 필드를 반환하지 않도록하려면 어떻게해야합니까? 암호 필드는 해시되지만 반환되지 않아야합니다.
암호 필드를 생략하고 간단한 쿼리에서 나머지 필드를 반환 할 수 있다는 것을 알고 있지만 채우기로 어떻게 수행합니까? 또한 이것을 수행하는 우아한 방법이 있습니까?
또한 사용자가 로그인하거나 암호를 변경하려는 경우와 같은 일부 상황에서는 암호 필드를 가져와야합니다.
.populate('user' , '-password')
http://mongoosejs.com/docs/populate.html
Schema 옵션을 사용하는 JohnnyHK의 대답은 아마도 여기로가는 방법 일 것입니다.
또한 query.exclude()
2.x 브랜치에만 존재합니다.
select
필드 의 속성을 사용하여 스키마 정의 레벨에서 기본 동작을 변경할 수 있습니다 .
password: { type: String, select: false }
그런 다음 필요에 따라 그것을 해낼 수 find
와 populate
같은 필드 선택을 통해 호출합니다 '+password'
. 예를 들면 :
Users.findOne({_id: id}).select('+password').exec(...);
편집하다:
두 가지 접근 방식을 모두 시도한 후, 항상 제외 접근 방식이 여권 로컬 전략을 사용하여 어떤 이유로 저에게 효과가 없다는 것을 알았습니다. 그 이유를 정말로 모릅니다.
그래서 이것은 내가 사용한 결과입니다.
Blogs.findOne({_id: id})
.populate("user", "-password -someOtherField -AnotherField")
.populate("comments.items.user")
.exec(function(error, result) {
if(error) handleError(error);
callback(error, result);
});
제외 항상 접근 방식에는 아무런 문제가 없으며 어떤 이유로 여권에서 작동하지 않았으며 테스트 결과 실제로 암호가 내가 원할 때 제외 / 포함되었다고 말했습니다. include always 접근 방식의 유일한 문제는 기본적으로 데이터베이스에 대한 모든 호출을 수행하고 많은 작업이 필요한 암호를 제외해야한다는 것입니다.
몇 가지 훌륭한 답변을 한 후 두 가지 방법이 있음을 알았습니다. "때때로 항상 포함 및 제외"와 "때때로 항상 제외 및 포함"?
둘 다의 예 :
항상 포함하지만 때로는 제외 예제 :
Users.find().select("-password")
또는
Users.find().exclude("password")
예외는 항상 있지만 때로는 예를 포함합니다 .
Users.find().select("+password")
그러나 스키마에서 정의해야합니다.
password: { type: String, select: false }
User.find().select('-password')
정답입니다. select: false
로그인을 원하면 작동하지 않으므로 스키마에 추가 할 수 없습니다 .
예를 들어 다음과 같은 스키마를 사용하여이를 달성 할 수 있습니다.
const UserSchema = new Schema({/* */})
UserSchema.set('toJSON', {
transform: function(doc, ret, opt) {
delete ret['password']
return ret
}
})
const User = mongoose.model('User', UserSchema)
User.findOne() // This should return an object excluding the password field
비밀번호 필드가 "password"라고 가정하면 다음을 수행 할 수 있습니다.
.exclude('password')
여기에 더 광범위한 예가 있습니다.
그것은 댓글에 초점을 맞추고 있지만, 동일한 원리입니다.
이것은 MongoDB의 쿼리에서 프로젝션을 사용 {"password" : 0}
하고 프로젝션 필드를 전달하는 것과 동일 합니다. 여기를 참조 하십시오
내 REST JSON 응답에서 비밀번호 필드 숨기기에 사용하고 있습니다.
UserSchema.methods.toJSON = function() {
var obj = this.toObject();
delete obj.password;
return obj;
}
module.exports = mongoose.model('User', UserSchema);
해결책은 일반 텍스트 암호를 저장하지 않는 것입니다. bcrypt 또는 password-hash 와 같은 패키지를 사용해야합니다 .
암호를 해시하는 사용 예 :
var passwordHash = require('password-hash');
var hashedPassword = passwordHash.generate('password123');
console.log(hashedPassword); // sha1$3I7HRwy7$cbfdac6008f9cab4083784cbd1874f76618d2a97
비밀번호 확인을위한 사용 예 :
var passwordHash = require('./lib/password-hash');
var hashedPassword = 'sha1$3I7HRwy7$cbfdac6008f9cab4083784cbd1874f76618d2a97';
console.log(passwordHash.verify('password123', hashedPassword)); // true
console.log(passwordHash.verify('Password0', hashedPassword)); // false
DocumentToObjectOptions 객체를 schema.toJSON () 또는 schema.toObject ()에 전달할 수 있습니다 .
@ types / mongoose의 TypeScript 정의 참조
/**
* The return value of this method is used in calls to JSON.stringify(doc).
* This method accepts the same options as Document#toObject. To apply the
* options to every document of your schema by default, set your schemas
* toJSON option to the same argument.
*/
toJSON(options?: DocumentToObjectOptions): any;
/**
* Converts this document into a plain javascript object, ready for storage in MongoDB.
* Buffers are converted to instances of mongodb.Binary for proper storage.
*/
toObject(options?: DocumentToObjectOptions): any;
DocumentToObjectOptions 에는 문서를 javascript 객체로 변환 한 후 사용자 정의 함수를 실행하는 변환 옵션이 있습니다. 여기에서 필요에 따라 속성을 숨기거나 수정할 수 있습니다.
따라서 schema.toObject ()를 사용 중이고 사용자 스키마에서 비밀번호 경로를 숨기고 싶다고 가정 해 보겠습니다. 모든 toObject () 호출 후에 실행될 일반 변환 함수를 구성해야합니다.
UserSchema.set('toObject', {
transform: (doc, ret, opt) => {
delete ret.password;
return ret;
}
});
Blogs.findOne({ _id: id }, { "password": 0 }).populate("user").exec()
사용하는 동안 password: { type: String, select: false }
인증에 필요할 때 비밀번호도 제외된다는 점을 명심해야합니다. 그러니 원하는대로 처리 할 준비를하십시오.
This is more a corollary to the original question, but this was the question I came across trying to solve my problem...
Namely, how to send the user back to the client in the user.save() callback without the password field.
Use case: application user updates their profile information/settings from the client (password, contact info, whatevs). You want to send the updated user information back to the client in the response, once it has successfully saved to mongoDB.
User.findById(userId, function (err, user) {
// err handling
user.propToUpdate = updateValue;
user.save(function(err) {
// err handling
/**
* convert the user document to a JavaScript object with the
* mongoose Document's toObject() method,
* then create a new object without the password property...
* easiest way is lodash's _.omit function if you're using lodash
*/
var sanitizedUser = _.omit(user.toObject(), 'password');
return res.status(201).send(sanitizedUser);
});
});
I found another way of doing this, by adding some settings to schema configuration.
const userSchema = new Schema({
name: {type: String, required: false, minlength: 5},
email: {type: String, required: true, minlength: 5},
phone: String,
password: String,
password_reset: String,
}, { toJSON: {
virtuals: true,
transform: function (doc, ret) {
delete ret._id;
delete ret.password;
delete ret.password_reset;
return ret;
}
}, timestamps: true });
By adding transform function to toJSON object with field name to exclude. as In docs stated:
We may need to perform a transformation of the resulting object based on some criteria, say to remove some sensitive information or return a custom object. In this case we set the optional
transform
function.
'IT박스' 카테고리의 다른 글
왜 C ++의 모든 것에 포인터를 사용하지 않습니까? (0) | 2020.10.20 |
---|---|
PHP 변환 날짜 형식 dd / mm / yyyy => yyyy-mm-dd (0) | 2020.10.20 |
Android ListView 선택한 항목이 강조 표시됨 (0) | 2020.10.20 |
플래시 기반 웹 사이트가 왜 그렇게 나쁜가요? (0) | 2020.10.20 |
Console.WriteLine을 사용하여 열의 텍스트를 어떻게 정렬 할 수 있습니까? (0) | 2020.10.20 |