“哇,这有效,为什么会发生这种情况?我目前正在使用我在 express 应用程序中设置为渲染引擎的 express-handlebars (3.1.0)。” – 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 - 以这个 sn-p 为例来重写你的 express 服务器
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));
});
你的猫鼬查询
如果我错了,请纠正我,但我认为这可能适用于您的查询...
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;
});