Express Handlebars 不会呈现数据

Express Handlebars Won't Render Data

我正在使用 Express-Handlebars 模板引擎处理 NodeJS 和 Express。

Handlebars 在尝试呈现模板时抛出以下错误:

Handlebars: Access has been denied to resolve the property "username" because it is not an "own property" of its parent. You can add a runtime option to disable the check or this warning: See https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access for details

根据上述link:

From version 4.6.0 on, Handlebars forbids accessing prototype properties and methods of the context object by default. The reason are various security issues that arise from this possibility.

我的 app.js 包含以下内容:

const exphbs = require('express-handlebars');
const express = require('express');
// Init Express
const app = express();
// VIEW ENGINE
app.engine('handlebars', exphbs({
  defaultLayout: 'main'
}));
app.set('view engine', 'handlebars');

我的路由文件通过 Mongoose 从 MongoDB 获取:

//@GET - View
router.get('/', authMiddleware, (req, res, next) => {
  // Mongoose
  Model.find({ user: req.user._id })
    .sort({ date: -1 })
    .then(model => {
      res.render('/overview', { model: model })
    })
    .catch(err => {
      if (err) throw err;
      req.flash('error_msg', 'No Model Found');
    })

})

模型是一个对象数组

这个问题是在我开始胡思乱想添加车把助手后才开始出现的。我已经删除了助手并恢复到我的原始配置设置(上方)无济于事。我试过删除 node_modules 文件夹并重新安装 npm。

发送的是一个对象数组,我正在尝试使用 {{#each model}} 助手遍历对象的属性,并通过 {{prop1}} 在每个对象中引用各个属性.

根据 Handlebars 的说法,默认情况下禁用 proto 属性是错误的,并且此更改不会破坏任何内容。

我的问题:

  1. 我是否错误地向车把发送了数据?如果是这样,将数据发送到 express-handlebars 模板进行渲染的正确方法是什么(不让我的服务器暴露于安全漏洞)?

提前谢谢你。

正确!我曾经与 Sequelize 一起工作,toJSON() 成功了。

如果您已经尝试过但没有成功,我认为使用 lean – mas 2 小时前

也可以在 Mongoose 中实现相同的结果

我在 .sort().then() 之间添加了 .lean,这成功了!

@OctavianLabs 的回答对我很有帮助:

const posts = await this.find({})
 .limit(amount)
 .lean();

mongoose returns 普通 JavaScript 对象 (POJO) 的 lean 方法,而不是 Mongoose 文档。

@OctavianLabs 对于那种 error.you 应该尝试下面的代码。

 Model.find({ user: req.user._id })
    .sort({ date: -1 })
    .lean()
    .then(model => {
      res.render('/overview', { model: model })
    })

我在升级 handlebars 包时遇到了同样的问题。为了让您的系统尽快恢复联机,请删除 package.json 中的 handlebars 条目,然后将此行插入它的位置。

"handlebars": "4.5.3",

从 4.6.0 版本开始,Handlebars 默认禁止访问上下文对象的原型属性和方法。这与此处描述的安全问题有关: https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html

参考 https://github.com/wycats/handlebars.js/issues/1642

上面的示例 URL 显示了转换为 JSON:

的 Mongoose 响应
app.get('/test', function (_req, res) {
    Kitten.find({}).then(kittens => {
        res.render('test.hbs', {
            kittens: kittens.map(kitten => kitten.toJSON())
        })
    })
});

如果您确定只有受信任的开发人员而没有最终用户可以访问车把模板,则可以通过安装以下软件包来允许原型访问:

npm install @handlebars/allow-prototype-access

这是一个使用示例:

const express = require('express');
const Handlebars = require('handlebars')
const expressHandlebars = require('express-handlebars');
const {allowInsecurePrototypeAccess} = require('@handlebars/allow-prototype-access')

const app = express();

app.engine('handlebars', expressHandlebars({
    handlebars: allowInsecurePrototypeAccess(Handlebars)
}));
app.set('view engine', 'handlebars');
...

另一种选择是使用 mongoose .lean() 函数。这具有比传统猫鼬查询快得多的好处。但它也有一些缺点。默认情况下,Mongoose 查询 return Mongoose 文档 class 的一个实例。这些对象包含大量用于更改跟踪的内部状态,并具有其他方法,例如 .save()。启用 lean 选项会告诉 Mongoose 跳过实例化完整的 Mongoose 文档,而只是 return 普通的 javascript 对象。

.find() 正常后使用 .lean()

在 .find() 之后使用 .lean() 此功能使数据获取速度更快