Express Handlebars 不会渲染数据

Coa*_*Cat 6 mongoose node.js express server-side-rendering express-handlebars

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

Handlebars 在尝试渲染模板时抛出以下错误:

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

根据上面的链接:

从 4.6.0 版本开始,Handlebars 默认禁止访问上下文对象的原型属性和方法。原因是这种可能性引起的各种安全问题。

我的 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');
Run Code Online (Sandbox Code Playgroud)

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

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');
Run Code Online (Sandbox Code Playgroud)

模型是一个对象数组

这个问题只是在我开始添加把手助手之后才开始发生。我已经删除了帮助程序并恢复到我的原始配置设置(上面)无济于事。我试过删除 node_modules 文件夹并重新安装 npm。

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

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

我的问题:

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

先感谢您。

And*_*lor 8

当我升级把手包时,我遇到了同样的问题。为了让您的系统尽快重新上线,请删除 package.json 中的 handlebars 条目,然后在其位置插入这一行。

"handlebars": "4.5.3",
Run Code Online (Sandbox Code Playgroud)

从 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())
        })
    })
});
Run Code Online (Sandbox Code Playgroud)

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

npm install @handlebars/allow-prototype-access
Run Code Online (Sandbox Code Playgroud)

这是它的使用示例:

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');
...
Run Code Online (Sandbox Code Playgroud)

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


Coa*_*Cat 7

正确的!我曾经Sequelize和我一起工作并toJSON()做到了这一点。

如果您已经尝试过但没有奏效,我认为在 Mongoose 中使用精益可以实现相同的结果2 小时前

我.lean在.sort()和之间添加.then(),这有效!


小智 6

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

  • 如果可能,请努力提供额外的解释,而不仅仅是代码。此类答案往往更有用,因为它们可以帮助社区成员(尤其是新开发人员)更好地理解解决方案的推理,并有助于避免解决后续问题。 (4认同)