Lenker: Der Zugriff zum Auflösen der Eigenschaft "von" wurde verweigert, da es sich nicht um eine "eigene Eigenschaft" des übergeordneten Elements handelt

15

Ich verwende ein Nodejs-Backend mit serverseitigem Rendering über den Lenker. Nach dem Lesen eines docArrays von Objekten aus dem Lenker, das die Schlüssel "Inhalt" und "Von" enthält. Wenn ich jedoch versuche, #eachdas Array von Objekten zu durchlaufen, wird der Fehler "Lenker: Zugriff verweigert, um die Eigenschaft" von "aufzulösen, da es sich nicht um eine" eigene Eigenschaft "des übergeordneten Objekts handelt.

Ich habe versucht, die Daten, die ich im doc-Array abgerufen habe, zu console.log (), und alles scheint in Ordnung zu sein.

In mancher Hinsicht ist dies die Mungo-Abfrage.
Ich habe das Objektdokument als Schlüssel in den res.render-Argumenten hinzugefügt.

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

Dies ist der Teil der .hbs-Datei, den ich durchlaufen möchte:

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

Antworten:

25

Ich löse dieses Problem, indem ich eine Entwicklungsabhängigkeit für den Lenker installiere

npm i -D [email protected]

Mason
quelle
Wow das hat funktioniert, warum passiert das aber? Ich verwende derzeit Express-Lenker (3.1.0), die ich in meiner Express-App als Render-Engine festgelegt habe.
Lee Boon Kong
Ich vermute, dass dies aufgrund einiger Einschränkungen bei neueren Versionen des Lenkers passiert ist, aber ich weiß nicht, wie ich mit diesen Einschränkungen umgehen soll.
Lee Boon Kong
Nun, das Problem liegt zwischen dem Express-Plugin, das den Lenker unterstützt, aber sobald der Lenker 4.5.0 als Hauptmodul Ihres Frontends gespeichert ist, lassen Sie es mich bitte wissen, indem Sie dies kommentieren.
Mason
Das funktioniert nicht. Immer noch das gleiche Problem, nachdem ich npm i -D [email protected]
Deepak Thakur
Die richtige Antwort finden Sie hier github.com/wycats/handlebars.js/issues/1642
Deepak Thakur
12

Wenn Sie Mungo verwenden, kann dieses Problem mithilfe von .lean () behoben werden, um ein JSON-Objekt (anstelle eines Mungos) abzurufen:

dbName.find({}).lean()
  // execute query
  .exec(function(error, body) {
     //Some code
  });
Billeh
quelle
3
Gott schütze dich! LEBENSRETTER!
Nick Thenick
1
Kein Problem, froh, dass es geholfen hat !!
Billeh
2
Ich wünschte, ich könnte diese Antwort mehr als einmal positiv bewerten. haha ​​Vielen Dank!
Abdus
7

Heute habe ich die gleiche Warnung vom Lenker und die Ansicht ist leer. Unten ist, wie ich das behoben habe:

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

die Datei users.hbs

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

Das Erstellen eines neuen Objekts contextmit eigenen Eigenschaften und die Übergabe an die Renderfunktion behebt das Problem ...

Hinweis:

Wenn wir kein neues Objekt erstellen, ist es leicht, versehentlich vertrauliche Informationen oder Informationen, die die Sicherheit des Projekts gefährden könnten, offenzulegen, die von der Datenbank zurückgegebenen Daten zuzuordnen und nur das zu übergeben, was für die Ansicht erforderlich ist ...

Drozerah
quelle
Vielen Dank für Ihre Antwort! Es scheint besser, ein neues Objekt zu erstellen, um eine unerwünschte Offenlegung von Daten zu verhindern.
Lee Boon Kong
Danke für diese Arbeit.
GNETO DOMINIQUE
Verbraucht das Rendern nicht zweimal Zeit, um eine neue Liste aus einer vorbereiteten Liste zu erstellen?
mustafiz012
6

"Wow, das hat funktioniert. Warum passiert das? Ich verwende derzeit Express-Lenker (3.1.0), die ich in meiner Express-App als Render-Engine festgelegt habe." - Lee Boon Kong 12. Januar um 14:13 Uhr

"In der Vergangenheit haben Sie mit Lenkern über die Vorlage auf Prototypmethoden und -eigenschaften des Eingabeobjekts zugegriffen ... Dieses Verhalten hat mehrere Sicherheitsprobleme verursacht ... In handlebars@^4.6.0. Zugriff auf den Objektprototyp wurde vollständig deaktiviert. Wenn Sie jetzt benutzerdefinierte Klassen als Eingabe für Lenker verwenden, funktioniert Ihr Code nicht mehr ... Dieses Paket fügt jedem Vorlagenaufruf automatisch Laufzeitoptionen hinzu und deaktiviert die Sicherheitsbeschränkungen ... Wenn Ihre Benutzer schreiben Vorlagen und Sie führen sie auf Ihrem Server aus. Sie sollten dieses Paket NICHT verwenden, sondern andere Wege finden, um das Problem zu lösen ...Ich schlage vor, dass Sie Ihre Klasseninstanzen in einfache JavaScript-Objekte konvertieren, bevor Sie sie an die Vorlagenfunktion übergeben. Jede Eigenschaft oder Funktion, auf die Sie zugreifen, muss eine "eigene Eigenschaft" des übergeordneten Elements sein. "- README

Weitere Informationen finden Sie hier: https://www.npmjs.com/package/@handlebars/allow-prototype-access

SCHNELLE UND SCHMUTZIGE SICHERHEITSMETHODE

Verwendung ( express-handlebarsund mongoose):

express-handlebarsSie können keine Laufzeitoptionen angeben, die an die Vorlagenfunktion übergeben werden sollen. Mit diesem Paket können Sie Prototypprüfungen für Ihre Modelle deaktivieren.

"Tun Sie dies nur, wenn Sie die volle Kontrolle über die Vorlagen haben, die auf dem Server ausgeführt werden."

Schritte:

1 - Abhängigkeit installieren

npm i @handlebars/allow-prototype-access

2 - Verwenden Sie dieses Snippet als Beispiel, um Ihren Express-Server neu zu schreiben

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 - Führen Sie den Server aus und tanzen Sie fröhlich.


LÄNGERE SICHERE METHODE

Bevor Sie das von Ihrem AJAX-Aufruf zurückgegebene Objekt an die Handlebars-Vorlage übergeben, ordnen Sie es mit jeder Eigenschaft oder Funktion, auf die Sie in Ihrer .hbsDatei zugreifen müssen, einem neuen Objekt zu . Unten sehen Sie das neue Objekt, das erstellt wurde, bevor es an die Lenkervorlage übergeben wurde.

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

Ihre Mungo-Anfrage

Korrigieren Sie mich, wenn ich falsch liege, aber ich denke, dass dies für Ihre Anfrage funktionieren könnte ...

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
quelle
5

versuchen Sie npm Install Lenker Version 4.5.3

npm installiere [email protected]

Es hat bei mir funktioniert

OOO Gold
quelle
Dies sollte ein Kommentar sein
Arun Vinoth
Ich benutzte derzeit Express-Lenker, Version 3.1.0
Lee Boon Kong
Danke, ich habe versucht, dass sowohl Ihre als auch @ Masons Antwort funktionieren würden, aber ich bin mir nicht sicher, warum dies geschieht.
Lee Boon Kong
3

Ab Version 4.6.0 verbietet Handlebars standardmäßig den Zugriff auf Prototypeneigenschaften und -methoden des Kontextobjekts. Dies hängt mit einem hier beschriebenen Sicherheitsproblem zusammen: https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html

Siehe https://github.com/wycats/handlebars.js/issues/1642

Wenn Sie sicher sind, dass nur Entwickler Zugriff auf die Vorlagen haben, können Sie den Prototypzugriff zulassen, indem Sie das folgende Paket installieren:

npm i @handlebars/allow-prototype-access

Wenn Sie einen Express-Lenker verwenden, gehen Sie wie folgt vor:

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
quelle
Danke das hat funktioniert. Also müssen wir das jedes Mal tun, wenn wir Express-Lenker verwenden müssen?
Yash Boura
2

In der jüngsten Version von Lenker gab es eine grundlegende Änderung, die diesen Fehler verursacht hat.

Sie können einfach die Konfigurationen hinzufügen, die sie in ihrer Dokumentation vorschlagen. Beachten Sie jedoch, dass dies abhängig von Ihrer Implementierung zu einer Anfälligkeit für XXS- und RCE-Angriffe führen kann.

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
quelle
Ahhh, hier füge ich die Optionen hinzu. Vielen Dank!
Lee Boon Kong
1
Das hat bei mir nicht funktioniert. Es wurde ein Rückruf erwartet, kein Optionsobjekt.
mrg95
0

Das Erstellen eines weiteren neuen Objekts oder Arrays aus den von zurückgegebenen Daten find() löst das Problem. Siehe unten eine einfache Abbildung

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
quelle