Kierownice: odmówiono dostępu w celu rozwiązania właściwości „z”, ponieważ nie jest ona „własnością własną” jej rodzica

15

Używam zaplecza Nodejsa z renderowaniem po stronie serwera za pomocą kierownicy. Po odczytaniu doctablicy obiektów z kierownicy, która zawiera kluczowe „treść” i „z”. Jednak gdy próbuję użyć #eachpętli do przeszukiwania tablicy obiektów, pojawia się błąd „Kierownica: odmowa dostępu do rozwiązania właściwości„ z ”, ponieważ nie jest to„ własność własna ”jej obiektu nadrzędnego.

Próbowałem console.log () danych, które pobrałem do tablicy dokumentów i wszystko wydaje się w porządku.

Dla niektórych perspektyw jest to zapytanie mangustowe,
dodałem dokument obiektowy jako klucz w argumentach 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;
  });

To część pliku .hbs, przez którą próbuję wykonać pętlę:

 {{#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
źródło

Odpowiedzi:

25

Rozwiązuję ten problem, instalując zależność dev dla kierownic

npm i -D [email protected]

Mason
źródło
Wow, zadziałało. Dlaczego tak się dzieje? Obecnie używam kierownicy ekspresowej (3.1.0), którą ustawiłem jako silnik renderowania w mojej aplikacji ekspresowej.
Lee Boon Kong
Podejrzewam, że działo się tak w przypadku nowszej wersji kierownicy z powodu pewnych ograniczeń, ale nie wiem, jak pracować nad tymi ograniczeniami.
Lee Boon Kong
Problem leży między wtyczką ekspresową, która obsługuje kierownicę, ale gdy kierownica 4.5.0 zostanie zapisana do użycia jako główny silnik interfejsu użytkownika, uprzejmie daj mi znać, komentując to.
Mason
To nie działa. Nadal dostaję ten sam problem po uruchomieniu npm i -D [email protected]
Deepak Thakur
Prawidłowa odpowiedź jest tutaj github.com/wycats/handlebars.js/issues/1642
Deepak Thakur
12

Jeśli używasz mangusty, ten problem można rozwiązać za pomocą .lean (), aby uzyskać obiekt json (zamiast mangusty):

dbName.find({}).lean()
  // execute query
  .exec(function(error, body) {
     //Some code
  });
Billeh
źródło
3
Niech cię Bóg błogosławi! OSZCZĘDNOŚĆ ŻYCIA!
Nick Thenick
1
Nie ma problemu, cieszę się, że to pomogło !!
Billeh
2
szkoda, że ​​nie mogę głosować więcej niż raz .. haha ​​Dziękuję bardzo!
Abdus
7

Dzisiaj mam takie samo ostrzeżenie z kierownicy i widok jest pusty. Poniżej znajduje się sposób, w jaki to naprawiłem:

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

plik users.hbs

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

Utworzenie całego nowego obiektu o contextwłasnych właściwościach, a następnie przekazanie go do funkcji renderowania naprawi problem ...

Uwaga:

Gdy nie tworzymy nowego obiektu, łatwo jest przypadkowo ujawnić poufne informacje lub informacje, które mogłyby zagrozić bezpieczeństwu projektu, mapowanie danych zwróconych z bazy danych i przekazywanie tylko tego, co jest potrzebne do widoku, może być dobrą praktyką ...

Drozerah
źródło
Wielkie dzięki za odpowiedź! Wydaje się, że lepiej jest utworzyć nowy obiekt, aby zapobiec niepożądanemu ujawnieniu danych.
Lee Boon Kong
Dzięki za tę pracę.
GNETO DOMINIQUE
Czy renderowanie nie zajmuje 2x czasu przez przygotowanie nowej listy z przygotowanej listy?
mustafiz012
6

„Wow, to zadziałało, dlaczego tak się dzieje? Obecnie używam kierownicy ekspresowej (3.1.0), którą ustawiłem jako silnik renderowania w mojej aplikacji ekspresowej”. - Lee Boon Kong 12 stycznia o 14:13

„W przeszłości kierownica umożliwiała dostęp do metod prototypowych i właściwości obiektu wejściowego z szablonu ... Z tego zachowania wynikało wiele problemów bezpieczeństwa ... W kierownicy@^4.6.0 dostęp do prototypu obiektu ma został całkowicie wyłączony. Teraz, jeśli użyjesz niestandardowych klas jako danych wejściowych do Kierownicy, Twój kod nie będzie już działał ... Ten pakiet automatycznie dodaje opcje środowiska wykonawczego do każdego wywołania szablonu, wyłączając ograniczenia bezpieczeństwa ... Jeśli użytkownicy piszą szablony i wykonujesz je na swoim serwerze, NIE powinieneś używać tego pakietu, ale raczej znaleźć inne sposoby rozwiązania problemu ...Sugeruję konwersję instancji klasy na zwykłe obiekty JavaScript przed przekazaniem ich do funkcji szablonu. Każda właściwość lub funkcja, do której masz dostęp, musi być „własną własnością” jej rodzica. ”- README

Więcej informacji tutaj: https://www.npmjs.com/package/@handlebars/allow-prototype-access

SZYBKA I BRUDNA METODA BEZPIECZEŃSTWA

Zastosowanie ( express-handlebarsi mongoose):

express-handlebarsnie pozwala określić opcji środowiska wykonawczego, które mają zostać przekazane do funkcji szablonu. Ten pakiet może pomóc w wyłączeniu kontroli prototypów dla twoich modeli.

„Zrób to tylko, jeśli masz pełną kontrolę nad szablonami wykonywanymi na serwerze”.

Kroki:

1 - Zainstaluj zależność

npm i @handlebars/allow-prototype-access

2 - Użyj tego fragmentu kodu jako przykładu do przepisania serwera ekspresowego

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 - Uruchom serwer i wykonuj swój szczęśliwy taniec.


DŁUŻSZA WIĘCEJ BEZPIECZNA METODA

Przed przekazaniem obiektu zwróconego przez wywołanie AJAX do szablonu Kierownicy zamapuj go na nowy obiekt z każdą właściwością lub funkcją, do której chcesz uzyskać dostęp w .hbspliku. Poniżej możesz zobaczyć nowy obiekt wykonany przed przekazaniem go do szablonu Kierownicy.

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

Twoje zapytanie mangusty

Popraw mnie, jeśli się mylę, ale myślę, że to może zadziałać dla twojego zapytania ...

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
źródło
5

spróbuj npm zainstalować kierownicę w wersji 4.5.3

npm install [email protected]

To zadziałało dla mnie

OOO Gold
źródło
To powinien być komentarz
Arun Vinoth
Obecnie korzystam z kierownicy ekspresowej, wersja 3.1.0
Lee Boon Kong
Dzięki, próbowałem zadziałać zarówno u ciebie, jak i @ Masona, ale nie jestem pewien, dlaczego tak się dzieje.
Lee Boon Kong
3

Począwszy od wersji 4.6.0 Kierownica domyślnie zabrania dostępu do właściwości prototypu i metod obiektu kontekstu. Jest to związane z opisanym tutaj problemem bezpieczeństwa: https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html

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

Jeśli masz pewność, że tylko programiści mają dostęp do szablonów, możesz zezwolić na dostęp prototypowy, instalując następujący pakiet:

npm i @handlebars/allow-prototype-access

Jeśli używasz kierownicy ekspresowej, postępuj następująco:

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
źródło
Dzięki, to działało. Musimy to robić za każdym razem, gdy musimy używać kierownicy ekspresowej?
Yash Boura
2

W ostatniej wersji Kierownicy nastąpiła przełomowa zmiana, która spowodowała ten błąd.

Możesz po prostu dodać konfiguracje, które sugerują w swojej dokumentacji, jednak pamiętaj, że w zależności od implementacji może to doprowadzić do podatności na ataki XXS i 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
źródło
Ahhh, więc tutaj dodaję opcje, wielkie dzięki!
Lee Boon Kong
1
To nie działało dla mnie. Oczekiwano wywołania zwrotnego, a nie obiektu opcji.
mrg95
0

Utworzenie innego nowego obiektu lub tablicy z danych zwróconych przez find() rozwiąże problem. Zobacz poniżej prostą ilustrację

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
źródło