Lee*_*ong 43 javascript mongodb node.js express handlebars.js
我正在使用 Nodejs 后端,并使用把手进行服务器端渲染。doc
从车把读取对象数组后,其中包含键“content”和“from”。但是,当我尝试使用#each
循环遍历对象数组时,出现错误“Handlebars:访问已被拒绝解析属性“from”,因为它不是其父级的“自己的属性””。
我尝试 console.log() 我在文档数组中获取的数据,一切看起来都很好。
从某些角度来看,这是猫鼬查询,
我已将对象文档添加为 res.render 参数中的键。
Confession.find()
.sort({date: -1})
.then(function(doc){
for(var i=0; i < doc.length; i++){
//Check whether sender is anonymous
if (doc[i].from === "" || doc[i].from == null){
doc[i].from = "Anonymous";
}
//Add an extra JSON Field for formatted date
doc[i].formattedDate = formatTime(doc[i].date);
}
res.render('index', {title: 'Confession Box', success:req.session.success, errors: req.session.errors, confession: doc});
req.session.errors = null;
req.session.success = null;
});
Run Code Online (Sandbox Code Playgroud)
这是我尝试循环遍历的 .hbs 文件的部分:
{{#each confession}}
<div class="uk-card uk-card-default uk-card-body uk-margin uk-align-center uk-width-1-2@m" >
<div class="uk-text-bold">Message: </div>
<div>{{this.content}}</div>
<div>From: {{this.from}}</div>
<div>Posted: {{this.formattedDate}}</div>
</div>
{{/each}}
Run Code Online (Sandbox Code Playgroud)
Bil*_*leh 64
如果使用 mongoose,则可以通过使用 .lean() 获取 json 对象(而不是 mongoose 对象)来解决此问题:
dbName.find({}).lean()
// execute query
.exec(function(error, body) {
//Some code
});
Run Code Online (Sandbox Code Playgroud)
Dro*_*rah 11
今天,我收到了来自车把的相同警告,并且视图是空的。以下是我解决这个问题的方法:
// * USERS PAGE
// @description users route
// @returns ../views/users.hbs
router.get('/users', async (req, res) => {
// get all items from db collection
const collection = 'User'
await dbFindAllDocs(collection) // <=> wrapper for Model.find() ...
.then(documents => {
// create context Object with 'usersDocuments' key
const context = {
usersDocuments: documents.map(document => {
return {
name: document.name,
location: document.location
}
})
}
// rendering usersDocuments from context Object
res.render('users', {
usersDocuments: context.usersDocuments
})
})
.catch(error => res.status(500).send(error))
})
Run Code Online (Sandbox Code Playgroud)
users.hbs 文件
<ul>
{{#each usersDocuments}}
<li>name: {{this.name}} location: {{this.location}}</li>
{{/each}}
</ul>
Run Code Online (Sandbox Code Playgroud)
创建一个以context
自己的属性命名的全新对象,然后将其传入渲染函数将解决该问题...
笔记:
当我们不创建新对象时,很容易意外暴露机密信息或可能危及项目安全的信息,映射从数据库返回的数据并仅将需要的内容传递到视图可能是一个很好的做法...
小智 9
“哇,这有效,为什么会发生这种情况?我目前正在使用 express-handlebars (3.1.0),我在我的 express 应用程序中将其设置为渲染引擎。” – Lee Boon Kong 1 月 12 日 14:13
“过去,Handlebars 允许您从模板访问输入对象的原型方法和属性……这种行为产生了多个安全问题……在 handlebars@^4.6.0 中,对对象原型的访问具有已被完全禁用。现在,如果您使用自定义类作为 Handlebars 的输入,您的代码将不再工作...此包会自动为每个模板调用添加运行时选项,禁用安全限制...如果您的用户正在编写模板并且你在你的服务器上执行它们你不应该使用这个包,而是找到其他方法来解决问题......我建议您先将类实例转换为纯 JavaScript 对象,然后再将它们传递给模板函数。您访问的每个属性或函数都必须是其父级的“自己的属性”。” – 自述文件
更多细节在这里:https : //www.npmjs.com/package/@handlebars/allow-prototype-access
快速而肮脏的不安全方法
用法(
express-handlebars
和mongoose
):
express-handlebars
不允许您指定要传递给模板函数的运行时选项。该软件包可以帮助您禁用模型的原型检查。“只有在您完全控制服务器中执行的模板的情况下才这样做。”
脚步:
1 - 安装依赖
npm i @handlebars/allow-prototype-access
2 - 使用此代码段作为示例重写您的快速服务器
Run Code Online (Sandbox Code Playgroud)const express = require('express'); const mongoose = require('mongoose'); const Handlebars = require('handlebars'); const exphbs = require('express-handlebars'); // Import function exported by newly installed node modules. const { allowInsecurePrototypeAccess } = require('@handlebars/allow-prototype-access'); const PORT = process.env.PORT || 3000; const app = express(); const routes = require('./routes'); app.use(express.urlencoded({ extended: true })); app.use(express.json()); app.use(express.static('public')); // When connecting Handlebars to the Express app... app.engine('handlebars', exphbs({ defaultLayout: 'main', // ...implement newly added insecure prototype access handlebars: allowInsecurePrototypeAccess(Handlebars) }) ); app.set('view engine', 'handlebars'); app.use(routes); const MONGODB_URI = process.env.MONGODB_URI || >'mongodb://localhost/dbName'; mongoose.connect(MONGODB_URI); app.listen(PORT, function () { console.log('Listening on port: ' + PORT); });
3 - 运行服务器并跳舞。
在将您的 AJAX 调用返回的对象传递给 Handlebars 模板之前,将它映射到一个新对象,其中包含您需要在.hbs
文件中访问的每个属性或函数。下面您可以看到在将新对象传递给 Handlebars 模板之前创建的新对象。
const router = require("express").Router();
const db = require("../../models");
router.get("/", function (req, res) {
db.Article.find({ saved: false })
.sort({ date: -1 })
.then(oldArticleObject => {
const newArticleObject = {
articles: oldArticleObject.map(data => {
return {
headline: data.headline,
summary: data.summary,
url: data.url,
date: data.date,
saved: data.saved
}
})
}
res.render("home", {
articles: newArticleObject.articles
})
})
.catch(error => res.status(500).send(error));
});
Run Code Online (Sandbox Code Playgroud)
如果我错了,请纠正我,但我认为这可能适用于您的查询...
Confession.find()
.sort({ date: -1 })
.then(function (oldDoc) {
for (var i = 0; i < oldDoc.length; i++) {
//Check whether sender is anonymous
if (oldDoc[i].from === "" || oldDoc[i].from == null) {
oldDoc[i].from = "Anonymous";
}
//Add an extra JSON Field for formatted date
oldDoc[i].formattedDate = formatTime(oldDoc[i].date);
}
const newDoc = {
doc: oldDoc.map(function (data) {
return {
from: data.from,
formattedDate: data.formattedDate
}
})
}
res.render('index', { title: 'Confession Box', success: req.session.success, errors: req.session.errors, confession: newDoc.doc });
req.session.errors = null;
req.session.success = null;
});
Run Code Online (Sandbox Code Playgroud)
小智 7
从 4.6.0 版本开始,Handlebars 默认禁止访问上下文对象的原型属性和方法。这与此处描述的安全问题有关:https : //mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html
参考https://github.com/wycats/handlebars.js/issues/1642
如果您确定只有开发人员可以访问模板,则可以通过安装以下包来允许原型访问:
npm i @handlebars/allow-prototype-access
Run Code Online (Sandbox Code Playgroud)
如果您使用的是 express-handlebars,您应该按照以下步骤进行:
const
express = require('express'),
_handlebars = require('handlebars'),
expressHandlebars = require('express-handlebars'),
{allowInsecurePrototypeAccess} = require('@handlebars/allow-prototype-access')
const app = express()
app.engine('handlebars', expressHandlebars({
handlebars: allowInsecurePrototypeAccess(_handlebars)
}))
app.set('view engine', 'handlebars')
Run Code Online (Sandbox Code Playgroud)
解决此问题的更简洁方法是使用猫鼬文档 .toJSON() 方法。
let data = dbName.find({})
.exec(function(error, body) {
//Some code
});
data = data.toJSON()
//use {{data}} on .hbs template
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
39157 次 |
最近记录: |