Рули: Доступ запрещен для разрешения свойства «from», поскольку оно не является «собственным свойством» его родителя.

15

Я использую серверную часть Nodejs для рендеринга на стороне сервера с использованием рулей. После прочтения docмассива объектов из руля, который содержит ключи «content» и «from». Однако, когда я пытаюсь использовать #eachцикл в массиве объектов, появляется ошибка «Handlebars: Access было отказано в разрешении свойства« from », поскольку оно не является« собственным свойством »его родителя» ».

Я попытался console.log () данные, которые я выбрал в массиве doc, и все выглядит нормально.

С какой-то точки зрения это запрос mongoose,
я добавил объект doc в качестве ключа в аргументы 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;
  });

Это часть файла .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}}

Ли Бун Конг
источник

Ответы:

25

я решаю эту проблему, установив Dev-зависимость для руля

npm i -D handlebars@4.5.0

каменщик
источник
Вау, это сработало, почему это происходит? В настоящее время я использую экспресс-рули (3.1.0), которые я установил как движок рендеринга в своем экспресс-приложении.
Ли Бун Конг
Я подозреваю, что это происходило на более новой версии руля из-за некоторых ограничений, но я не знаю, как работать с этими ограничениями.
Ли Бун Конг
Что ж, проблема лежит между экспресс-плагином, который поддерживает рули, но как только руль 4.5.0 будет сохранен для использования в качестве основного движка вашего веб-интерфейса, пожалуйста, дайте мне знать, комментируя это.
Мейсон
Это не работает. По-прежнему возникает та же проблема после выполнения npm i -D handlebars@4.5.0
Дипак Тхакур
Правильный ответ здесь github.com/wycats/handlebars.js/issues/1642
Дипак Тхакур
13

При использовании mongoose эту проблему можно решить с помощью .lean (), чтобы получить объект json (вместо mongoose):

dbName.find({}).lean()
  // execute query
  .exec(function(error, body) {
     //Some code
  });
Billeh
источник
3
Будьте здоровы! ЭКОНОМИЯ ЖИЗНИ!
Ник Теник
1
Нет проблем, рад, что это помогло !!
Билле
2
Хотелось бы, чтобы я проголосовал за этот ответ не раз ... хаха Спасибо большое!
Абдус
7

Сегодня у меня такое же предупреждение от руля, и вид пуст. Вот как я это исправил:

//  * 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))
})

файл users.hbs

<ul>
{{#each usersDocuments}}
<li>name: {{this.name}} location: {{this.location}}</li>
{{/each}}    
</ul>

Создание целого нового объекта с именами contextсо своими собственными свойствами, а затем передача его в функцию рендера, решит проблему ...

нота:

Когда мы не создаем новый объект, легко случайно раскрыть конфиденциальную информацию или информацию, которая может поставить под угрозу безопасность проекта, сопоставление данных, возвращаемых из базы данных, и передачу только того, что необходимо для представления, может быть хорошей практикой ...

Drozerah
источник
Большое спасибо за ваш ответ! Кажется, лучше создать новый объект, чтобы предотвратить нежелательное раскрытие данных.
Ли Бун Конг
Спасибо за эту работу.
GNETO ДОМИНИКА
Разве это не потребует 2-кратного времени рендеринга при подготовке нового списка из подготовленного списка?
mustafiz012
6

«Да, это сработало. Почему это происходит? Я сейчас использую экспресс-рули (3.1.0), которые я установил в качестве механизма рендеринга в своем экспресс-приложении». - Ли Бун Конг 12 января в 14:13

«В прошлом Handlebars позволяли вам получать доступ к методам и свойствам прототипа объекта ввода из шаблона ... Из-за этого поведения возникли многочисленные проблемы безопасности ... В handlebars@^4.6.0. Доступ к прототипу объекта имеет полностью отключен. Теперь, если вы используете пользовательские классы в качестве входных данных для Handlebars, ваш код больше не будет работать ... Этот пакет автоматически добавляет параметры времени выполнения к каждому вызову шаблона, отключая ограничения безопасности ... Если ваши пользователи пишут шаблоны и вы выполняете их на своем сервере, вы не должны использовать этот пакет, а вместо этого найти другие способы решения проблемы ...Я предлагаю вам преобразовать ваши экземпляры классов в обычные объекты JavaScript, прежде чем передавать их в функцию шаблона. Каждое свойство или функция, к которой вы обращаетесь, должно быть "собственным свойством" своего родителя. "- README

Более подробная информация здесь: https://www.npmjs.com/package/@handlebars/allow-prototype-access

БЫСТРЫЙ И Грязный НЕОБХОДИМЫЙ МЕТОД

Использование ( express-handlebarsи mongoose):

express-handlebarsне позволяет указывать параметры времени выполнения для передачи в функцию шаблона. Этот пакет может помочь вам отключить проверку прототипов для ваших моделей.

«Делайте это только в том случае, если у вас есть полный контроль над шаблонами, которые выполняются на сервере».

шаги:

1 - установить зависимость

npm i @handlebars/allow-prototype-access

2 - Используйте этот фрагмент в качестве примера, чтобы переписать ваш экспресс-сервер

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;
    });
Джейсон Новак
источник
5

попробуйте npm установить руль версии 4.5.3

npm установить руль@4.5.3

У меня сработало

ООО Голд
источник
Это должен быть комментарий
Арун Винот
Я в настоящее время использую экспресс-руль, версия 3.1.0
Ли Бун Конг
Спасибо, я попробовал и ваше, и @ Mason's anwser сработает, но я не уверен, почему это происходит.
Ли Бун Конг
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.

Если вы уверены, что только разработчики имеют доступ к шаблонам, можно разрешить доступ к прототипу, установив следующий пакет:

npm i @handlebars/allow-prototype-access

Если вы используете экспресс-руль, вы должны действовать следующим образом:

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')
jm4rc05
источник
Спасибо, это сработало. Таким образом, мы должны это делать каждый раз, когда нам приходится использовать экспресс-руль?
Яш Бура
2

Было нарушение изменений в недавнем выпуске Рулей , который вызвал эту ошибку.

Вы можете просто добавить конфигурации, которые они предлагают, в свою документацию, однако помните, что в зависимости от вашей реализации это может привести к уязвимости к атакам XXS и RCE.

https://handlebarsjs.com/api-reference/runtime-options.html#options-to-control-prototype-access

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}, {

      // Options to allow access to the properties and methods which as causing the error.

      allowProtoMethodsByDefault: true,
      allowProtoPropertiesByDefault: true

    });

    req.session.errors = null;
    req.session.success = null;
  });
roydukkey
источник
Аааа, так вот где я добавляю варианты, большое спасибо!
Ли Бун Конг
1
Это не сработало для меня. Ожидался обратный вызов, а не объект параметров.
mrg95
0

Создание другого нового объекта или массива из данных, возвращаемых, find() решит проблему. Смотрите ниже простую иллюстрацию

app.get("/",(req,res)=>{

 let com = require('./MODELCOM')    // loading model
 let source=fs.readFileSync(__dirname+"/views/template.hbs","utf-8");

 com.find((err,data)=>{
    // creation new array  using map
   let wanted = data.map(doc=>{
       return {
           name:doc.name,
           _id:doc._id
        }
   })

    let html= handlebar.compile(source);
  fs.writeFileSync(__dirname+"/views/reciever.html",html({communities:wanted}))
    res.sendFile(__dirname+"/views/reciever.html")
});
ГНЕТО ДОМИНИКА
источник