Guidon: l'accès a été refusé pour résoudre la propriété «de» car il ne s'agit pas d'une «propriété propre» de son parent


15

J'utilise un backend Nodejs avec un rendu côté serveur à l'aide de guidons. Après avoir lu un doctableau d'objets à partir du guidon, qui contient les clés "contenu" et "de". Cependant, lorsque j'essaie d'utiliser #eachpour parcourir le tableau d'objets, l'erreur "Guidon: l'accès a été refusé pour résoudre la propriété" à partir de "car il ne s'agit pas d'une" propre propriété "de son parent" apparaît.

J'ai essayé de console.log () les données que j'ai récupérées dans le tableau doc ​​et tout semble bien.

Pour une certaine perspective, il s'agit de la requête mangouste,
j'ai ajouté l'objet doc en tant que clé dans les arguments 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;
  });

Voici la partie du fichier .hbs que j'essaie de parcourir:

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

Réponses:


25

je résout ce problème en installant une dépendance de dev pour les guidons

npm i -D handlebars@4.5.0


Wow cela a fonctionné, pourquoi cela se produit-il cependant? J'utilise actuellement un guidon express (3.1.0) que j'ai défini comme moteur de rendu dans mon application express.
Lee Boon Kong

Je soupçonne que cela se produisait sur une version plus récente du guidon en raison de certaines restrictions, mais je ne sais pas comment travailler sur ces restrictions.
Lee Boon Kong

Eh bien, le problème réside entre le plugin express qui prend en charge le guidon, mais une fois que le guidon 4.5.0 est enregistré pour être utilisé comme moteur principal de votre interface, veuillez me le faire savoir en commentant cela.
Mason

Cela ne fonctionne pas. Obtenez toujours le même problème après avoir exécuté npm i -D handlebars@4.5.0
Deepak Thakur


13

Si vous utilisez une mangouste, ce problème peut être résolu en utilisant .lean () pour obtenir un objet json (au lieu d'un mangouste):

dbName.find({}).lean()
  // execute query
  .exec(function(error, body) {
     //Some code
  });

3
Dieu te bénisse! LA VIE SAVEUR!
Nick Thenick

1
Pas de problème, content d'avoir aidé !!
Billeh

2
j'aimerais pouvoir voter cette réponse plus d'une fois .. haha ​​Merci beaucoup!
Abdus

7

Aujourd'hui, j'ai le même avertissement du guidon et la vue est vide. Voici comment j'ai corrigé cela:

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

le fichier users.hbs

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

Créer un nouvel objet entier nommé contextavec ses propres propriétés, puis le passer dans la fonction de rendu résoudra le problème ...

Remarque:

Lorsque nous ne créons pas un nouvel objet, il est facile d'exposer accidentellement des informations confidentielles ou des informations qui pourraient compromettre la sécurité du projet, le mappage des données renvoyées par la base de données et le passage de ce qui est nécessaire dans la vue peut être une bonne pratique. ...


Merci beaucoup pour votre réponse! Il semble préférable de créer un nouvel objet pour éviter l'exposition indésirable de données.
Lee Boon Kong

Merci pour ce travail.
GNETO DOMINIQUE

Est-ce que cela ne prend pas 2x de temps pour le rendu en préparant une nouvelle liste à partir d'une liste préparée?
mustafiz012

6

"Wow cela a fonctionné, pourquoi est-ce que cela se produit cependant? J'utilise actuellement un guidon express (3.1.0) que j'ai défini comme moteur de rendu dans mon application express." - Lee Boon Kong 12 janvier à 14h13

"Dans le passé, les guidons vous permettaient d'accéder aux méthodes et aux propriétés du prototype de l'objet d'entrée à partir du modèle ... Plusieurs problèmes de sécurité sont dus à ce comportement ... Dans le guidon@^4.6.0. L'accès au prototype d'objet a Désormais, si vous utilisez des classes personnalisées comme entrée pour les guidons, votre code ne fonctionnera plus ... Ce package ajoute automatiquement des options d'exécution à chaque modèle d'appels, désactivant les restrictions de sécurité ... Si vos utilisateurs écrivent modèles et que vous les exécutez sur votre serveur, vous ne devez PAS utiliser ce package, mais plutôt trouver d'autres moyens de résoudre le problème ...Je vous suggère de convertir vos instances de classe en objets JavaScript simples avant de les transmettre à la fonction de modèle. Chaque propriété ou fonction à laquelle vous accédez doit être une "propriété propre" de son parent. "- LISEZ-MOI

Plus de détails ici: https://www.npmjs.com/package/@handlebars/allow-prototype-access

MÉTHODE D'INSECURE RAPIDE ET SALÉE

Utilisation ( express-handlebarset mongoose):

express-handlebarsne vous permet pas de spécifier des options d'exécution à passer à la fonction de modèle. Ce package peut vous aider à désactiver les vérifications de prototype pour vos modèles.

"Ne faites cela que si vous avez un contrôle total sur les modèles exécutés sur le serveur."

Pas:

1 - Installer la dépendance

npm i @handlebars/allow-prototype-access

2 - Utilisez cet extrait de code comme exemple pour réécrire votre serveur 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 - Exécutez le serveur et faites votre danse heureuse.


MÉTHODE PLUS LONGUE ET SÉCURISÉE

Avant de passer l'objet renvoyé par votre appel AJAX au modèle Handlebars, mappez-le dans un nouvel objet avec chaque propriété ou fonction à laquelle vous devez accéder dans votre .hbsfichier. Ci-dessous, vous pouvez voir le nouvel objet créé avant de le passer au modèle 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));
});

Votre requête mangouste

Corrigez-moi si je me trompe, mais je pense que cela pourrait fonctionner pour votre requête ...

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

essayez npm install guidon version 4.5.3

npm install guidon@4.5.3

Ça a marché pour moi


Cela devrait être un commentaire
Arun Vinoth

J'utilisais actuellement le guidon express, version 3.1.0
Lee Boon Kong

Merci, j'ai essayé les vôtres et la réponse de @ Mason fonctionnerait, mais je ne sais pas pourquoi cela se produit.
Lee Boon Kong

3

À partir de la version 4.6.0, Handlebars interdit l'accès par défaut aux propriétés et méthodes du prototype de l'objet contextuel. Ceci est lié à un problème de sécurité décrit ici: https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html

Reportez-vous à https://github.com/wycats/handlebars.js/issues/1642

Si vous êtes certain que seuls les développeurs ont accès aux modèles, il est possible d'autoriser l'accès au prototype en installant le package suivant:

npm i @handlebars/allow-prototype-access

Si vous utilisez un guidon express, vous devez procéder comme suit:

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')

Merci, cela a fonctionné. Nous devons donc à chaque fois que nous devons utiliser des guidons express?
Yash Boura

2

Il y a eu un changement de rupture dans la récente version de Guidon qui a provoqué cette erreur.

Vous pouvez simplement ajouter les configurations suggérées dans leur documentation, mais sachez que, selon votre implémentation, cela pourrait entraîner la vulnérabilité aux attaques XXS et 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;
  });

Ahhh donc c'est là que j'ajoute les options, merci beaucoup!
Lee Boon Kong

1
Ça n'a pas marché pour moi. Un rappel était attendu, pas un objet d'options.
mrg95

0

La création d'un autre nouvel objet ou tableau à partir des données renvoyées par find() résoudra le problème. Voir ci-dessous une illustration simple

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")
});
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.