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

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

Я попытался console.log () получить данные, которые я извлек в массив do c, и все выглядит нормально.

Для некоторой перспективы это запрос mon goose,
Я добавил объект do c в качестве ключа в аргументах 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, которую я пытаюсь l oop через:

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

Ответы [ 8 ]

25 голосов
/ 12 января 2020

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

npm i -D handlebars@4.5.0

13 голосов
/ 24 февраля 2020

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

dbName.find({}).lean()
  // execute query
  .exec(function(error, body) {
     //Some code
  });
7 голосов
/ 13 января 2020

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

//  * 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 со своими собственными свойствами и передача его в рендер функция решит проблему ...

примечание:

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

6 голосов
/ 04 марта 2020

"Ух ты, это сработало, почему это происходит? Я сейчас использую express -пульки (3.1.0), которые я установил как движок рендеринга в своем приложении express." - Ли Бун Конг 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 - Используйте этот фрагмент в качестве примера для перезаписи вашего 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));
});

Ваш мон goose запрос

Исправьте меня, если я ошибаюсь, но я думаю, что это может сработать по вашему запросу ...

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 голосов
/ 11 января 2020

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

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

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

3 голосов
/ 21 апреля 2020

Начиная с версии 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

Если вы используете express -handlebars, вы должны выполнить следующие действия:

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')
2 голосов
/ 13 января 2020

В последнем выпуске Handlebars произошло критическое изменение , которое вызвало эту ошибку.

Вы можете просто добавить конфигурации, которые они предлагают, в своей документации, однако учтите, что в зависимости от вашей реализации это может привести к уязвимости к атакам 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;
  });
0 голосов
/ 14 февраля 2020

Создание еще одного нового объекта или массива из данных, возвращаемых 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")
});
...