温馨提示:本文翻译自stackoverflow.com,查看原文请点击:node.js - Express Handlebars Won't Render Data

node.js - Express把手不会渲染数据

发布于 2020-03-27 15:54:59

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

尝试渲染模板时,车把引发以下错误:

车把:拒绝访问以解析属性“用户名”,因为它不是其父项的“自有属性”。您可以添加运行时选项以禁用检查或此警告:有关 详细信息,请参见 https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access

根据上面的链接:

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.

My app.js contains the following:

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');

My route file fetches from MongoDB via Mongoose:

//@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');
    })

})

model is an array of objects

This issue only started happening after I began to mess around with adding handlebar helpers. I have removed the helpers and reverted to my original configuration settings (above) to no avail. I've tried deleting node_modules folder and reinstalling npm.

What's being sent is an array of objects, and I am trying to loop over the properties of the objects using the {{#each model}} helper and reference the individual properties via {{prop1}} within the each.

According to Handlebars, this disabling of proto properties is false by default, and this change shouldn't break anything.

My question:

  1. Am I sending data to handlebars incorrectly? If so, what is the correct method (not exposing my server to security holes) to send data to the express-handlebars template for rendering?

Thank you in advance.

查看更多

查看更多

提问者
OctavianLabs
被浏览
95
Andrew Taylor 2020-03-02 04:57

I had the same issue when I upgraded the handlebars package. To get your system back online as quick as possible remove the handlebars entry in package.json And then insert this line in its place.

"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

上述网址的示例显示了将Mongoose响应转换为JSON的情况:

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 查询快得多的优点。但是它也确实有一些缺点。默认情况下,Mongoose查询返回Mongoose Document类的实例。这些对象包含许多用于更改跟踪的内部状态,并具有其他方法,例如.save()。启用lean选项可以使Mongoose跳过实例化完整的Mongoose文档,而只返回普通的javascript对象。