Guiador: acesso negado para resolver a propriedade "de" porque não é uma "propriedade própria" de seu pai

15

Estou usando um back-end do Nodejs com renderização do lado do servidor usando guidão. Depois de ler uma docvariedade de objetos no guidão, que contém os principais "conteúdo" e "de". No entanto, quando tento usar o #eachloop pela matriz de objetos, o erro "Guiador: acesso foi negado para resolver a propriedade" from "porque não é uma" propriedade própria "de seu pai" é exibida.

Eu tentei console.log () os dados que eu busquei na matriz de documentos e tudo parece bem.

Para alguma perspectiva, esta é a consulta mangusto,
adicionei o objeto doc como uma chave nos argumentos 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;
  });

Esta é a parte do arquivo .hbs que estou tentando fazer um loop:

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

Lee Boon Kong
fonte

Respostas:

25

eu resolvo esse problema instalando uma dependência de desenvolvedor para o guidão

npm i -D [email protected]

Pedreiro
fonte
Uau, isso funcionou. Por que isso está acontecendo? Atualmente, estou usando o guidão expresso (3.1.0), que defini como mecanismo de renderização no meu aplicativo expresso.
Lee Boon Kong
Eu suspeito que isso estava acontecendo na versão mais recente do guidão devido a algumas restrições, mas não sei como trabalhar com essas restrições.
Lee Boon Kong
Bem, o problema está entre o plug-in expresso que suporta o guidão, mas uma vez que o guidão 4.5.0 é salvo para ser usado como o principal mecanismo do seu front-end, informe-me comentando sobre isso.
Mason
Isto não está a funcionar. Ainda tenho o mesmo problema depois de executar o npm i -D [email protected]
Deepak Thakur
A resposta correta está aqui github.com/wycats/handlebars.js/issues/1642
Deepak Thakur
13

Se estiver usando o mangusto, esse problema pode ser resolvido usando .lean () para obter um objeto json (em vez de um mangusto):

dbName.find({}).lean()
  // execute query
  .exec(function(error, body) {
     //Some code
  });
Billeh
fonte
3
Deus te abençoê! SALVADOR DE VIDA!
Nick Thenick
11
Não tem problema, feliz que ajudou !!
Billeh 9/04
2
gostaria de poder votar esta resposta mais de uma vez .. haha ​​Muito obrigado!
Abdus
7

Hoje eu tenho o mesmo aviso no guidão e a vista está vazia. Abaixo está como eu consertei isso:

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

o arquivo users.hbs

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

Criar um novo objeto inteiro contextcom suas próprias propriedades e depois passá-lo para a função de renderização corrigirá o problema ...

Nota:

Quando não criamos um novo Objeto, é fácil expor acidentalmente informações confidenciais ou informações que possam comprometer a segurança do projeto, mapear os dados retornados do banco de dados e passar apenas o necessário para a exibição pode ser uma boa prática. ...

Drozerah
fonte
Muito obrigado pela sua resposta! Parece melhor criar um novo objeto para evitar a exposição indesejada de dados.
Lee Boon Kong
Obrigado por este trabalho.
GNETO DOMINIQUE
Não consome 2x o tempo para renderizar, preparando uma nova lista a partir de uma lista preparada?
mustafiz012 27/04
6

"Uau, isso funcionou. Por que isso está acontecendo? No momento, estou usando o guidão expresso (3.1.0), que defini como mecanismo de renderização no meu aplicativo expresso." - Lee Boon Kong 12/01 às 14:13

"No passado, o Handlebars permitia acessar métodos e propriedades do protótipo do objeto de entrada do modelo ... Vários problemas de segurança surgiram desse comportamento ... No handlebars@^4.6.0. O acesso ao protótipo do objeto foi Agora, se você usar classes personalizadas como entrada no guidão, seu código não funcionará mais ... Este pacote adiciona automaticamente opções de tempo de execução a cada chamada de modelo, desativando as restrições de segurança ... Se seus usuários estiverem escrevendo modelos e você os executa no servidor, NÃO deve usar este pacote, mas sim encontrar outras maneiras de resolver o problema ...Sugiro que você converta suas instâncias de classe em objetos JavaScript simples antes de passá-los para a função de modelo. Toda propriedade ou função que você acessa deve ser uma "propriedade própria" de seu pai. "- README

Mais detalhes aqui: https://www.npmjs.com/package/@handlebars/allow-prototype-access

MÉTODO INSEGURO RÁPIDO E SUJO

Uso ( express-handlebarse mongoose):

express-handlebarsnão permite especificar opções de tempo de execução para passar para a função de modelo. Este pacote pode ajudá-lo a desativar as verificações de protótipo para seus modelos.

"Faça isso apenas se você tiver controle total sobre os modelos executados no servidor."

Passos:

1 - Instalar dependência

npm i @handlebars/allow-prototype-access

2 - Use este trecho como exemplo para reescrever seu servidor expresso

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 - Execute o servidor e faça sua dança feliz.


MÉTODO MAIS SEGURO E MAIS SEGURO

Antes de passar o objeto retornado pela sua chamada AJAX para o modelo do Handlebars, mapeie-o em um novo objeto com cada propriedade ou função que você precisa acessar em seu .hbsarquivo. Abaixo, você pode ver o novo objeto criado antes de passá-lo para o modelo do guidão.

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

Sua consulta mangusto

Corrija-me se estiver errado, mas acho que isso pode funcionar para sua consulta ...

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;
    });
Jason Novak
fonte
5

tente o npm install handlebars versão 4.5.3

npm install [email protected]

Funcionou para mim

OOO Ouro
fonte
Isso deve ser um comentário
Arun Vinoth
Eu estava usando o guidão expresso, versão 3.1.0
Lee Boon Kong
Obrigado, tentei tanto a sua como a resposta do @ Mason funcionariam, mas não sei por que isso está acontecendo.
Lee Boon Kong
3

A partir da versão 4.6.0 em diante, o Handlebars proíbe o acesso a propriedades e métodos de protótipo do objeto de contexto por padrão. Isso está relacionado a um problema de segurança descrito aqui: https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html

Referir-se https://github.com/wycats/handlebars.js/issues/1642

Se você tem certeza de que apenas os desenvolvedores têm acesso aos modelos, é possível permitir o acesso ao protótipo instalando o seguinte pacote:

npm i @handlebars/allow-prototype-access

Se você estiver usando guidão expresso, proceda da seguinte forma:

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
fonte
Graças isso funcionou. Então, precisamos fazer isso sempre que precisamos usar guidão expresso?
Yash Boura 23/04
2

Houve uma mudança na versão recente do guidão que causou esse erro.

Você pode simplesmente adicionar as configurações sugeridas em sua documentação; no entanto, esteja ciente de que, dependendo da sua implementação, isso pode levar a vulnerabilidade a ataques XXS e 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
fonte
Ahhh, então é aí que eu adiciono as opções, Muito obrigado!
Lee Boon Kong
11
Isso não funcionou para mim. Era esperado um retorno de chamada, não um objeto de opções.
mrg95 20/01
0

Criar outro novo objeto ou matriz a partir dos dados retornados por find() resolverá o problema. Veja abaixo uma ilustração simples

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")
});
GNETO DOMINIQUE
fonte