Setang: Akses telah ditolak untuk menyelesaikan properti "dari" karena itu bukan "milik sendiri" dari induknya


15

Saya menggunakan backend Nodejs dengan rendering sisi server menggunakan setang. Setelah membaca docberbagai objek dari setang, yang berisi kunci "konten" dan "dari". Namun ketika saya mencoba menggunakan #eachuntuk loop melalui array objek, kesalahan "Setang: Akses telah ditolak untuk menyelesaikan properti" dari "karena itu bukan" milik sendiri "dari induknya" muncul.

Saya sudah mencoba untuk console.log () data yang telah saya ambil dalam array doc dan semuanya tampak baik-baik saja.

Untuk beberapa perspektif, ini adalah query luwak,
saya telah menambahkan objek doc sebagai kunci di dalam argumen 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;
  });

Ini adalah bagian dari file .hbs yang saya coba lewati:

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

Jawaban:


25

saya mengatasi masalah ini dengan menginstal dependensi dev untuk setang

npm i -D handlebars@4.5.0


Wow ini berhasil, Mengapa ini terjadi? Saat ini saya menggunakan setang ekspres (3.1.0) yang saya tetapkan sebagai mesin render di aplikasi ekspres saya.
Lee Boon Kong

Saya menduga ini terjadi pada versi setang yang lebih baru karena beberapa batasan, tetapi saya tidak tahu bagaimana cara mengatasi pembatasan ini.
Lee Boon Kong

Masalahnya ada di antara plugin express yang mendukung setang, tetapi begitu setang 4.5.0 disimpan untuk digunakan sebagai mesin utama dari frontend Anda, silakan beri tahu saya dengan mengomentari ini.
Mason

Ini tidak bekerja. Masih mendapatkan masalah yang sama setelah saya mengeksekusi npm i -D handlebars@4.5.0
Deepak Thakur


13

Jika menggunakan luwak, masalah ini dapat diselesaikan dengan menggunakan .lean () untuk mendapatkan objek json (bukan yang luwak):

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

3
Tuhan memberkati Anda! PENOLONG!
Nick Thenick

1
Tidak masalah, senang itu membantu !!
Billeh

2
Seandainya aku bisa memilih jawaban ini lebih dari satu kali .. haha ​​Terima kasih banyak!
Abdus

7

Hari ini saya mendapat peringatan yang sama dari setang dan tampilan kosong. Di bawah ini adalah bagaimana saya memperbaikinya:

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

file users.hbs

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

Membuat seluruh objek baru bernama contextdengan propertinya sendiri lalu meneruskannya ke dalam fungsi render akan memperbaiki masalah ...

catatan:

Ketika kita tidak membuat Obyek baru, mudah untuk secara tidak sengaja memaparkan informasi rahasia, atau informasi yang dapat membahayakan keamanan projet, memetakan data yang dikembalikan dari database dan hanya meneruskan apa yang diperlukan ke tampilan bisa menjadi praktik yang baik ...


Terima kasih banyak atas jawaban Anda! Tampaknya lebih baik untuk membuat objek baru untuk mencegah pemaparan data yang tidak diinginkan.
Lee Boon Kong

Terima kasih untuk pekerjaan ini.
GNETO DOMINIQUE

Bukankah itu menghabiskan 2x waktu untuk membuat dengan menyiapkan daftar baru dari daftar yang disiapkan?
mustafiz012

6

"Wow, ini berhasil, mengapa hal ini terjadi? Saat ini saya menggunakan setang ekspres (3.1.0) yang saya tetapkan sebagai mesin render di aplikasi kilat saya." - Lee Boon Kong 12 Jan pada 14:13

"Di masa lalu, Handlebars akan memungkinkan Anda untuk mengakses metode prototipe dan properti dari objek input dari templat ... Berbagai masalah keamanan berasal dari perilaku ini ... Di handlebars@^4.6.0. Akses ke objek prototipe memiliki telah dinonaktifkan sepenuhnya. Sekarang, jika Anda menggunakan kelas khusus sebagai input ke Setang, kode Anda tidak akan berfungsi lagi ... Paket ini secara otomatis menambahkan opsi runtime untuk setiap panggilan templat, menonaktifkan pembatasan keamanan ... Jika pengguna Anda menulis template dan Anda menjalankannya di server Anda, Anda TIDAK boleh menggunakan paket ini, tetapi mencari cara lain untuk memecahkan masalah ...Saya sarankan Anda mengonversi instance-class Anda ke objek JavaScript biasa sebelum meneruskannya ke fungsi templat. Setiap properti atau fungsi yang Anda akses, harus merupakan "milik sendiri" dari induknya. "- README

Lebih detail di sini: https://www.npmjs.com/package/@handlebars/allow-prototype-access

METODE KEAMANAN CEPAT DAN KOTOR

Penggunaan ( express-handlebarsdan mongoose):

express-handlebarstidak memungkinkan Anda untuk menentukan opsi runtime untuk diteruskan ke fungsi templat. Paket ini dapat membantu Anda menonaktifkan pemeriksaan prototipe untuk model Anda.

"Hanya lakukan ini, jika Anda memiliki kendali penuh atas templat yang dieksekusi di server."

Langkah:

1 - Instal dependensi

npm i @handlebars/allow-prototype-access

2 - Gunakan cuplikan ini sebagai contoh untuk menulis ulang server ekspres Anda

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 - Jalankan server dan lakukan tarian bahagia Anda.


METODE LEBIH LANJUT AMAN

Sebelum meneruskan objek yang dikembalikan oleh panggilan AJAX Anda ke templat Handlebars, petakan objek tersebut ke objek baru dengan setiap properti atau fungsi yang perlu Anda akses di .hbsfile Anda . Di bawah ini Anda dapat melihat objek baru yang dibuat sebelum meneruskannya ke template 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));
});

Permintaan luwak Anda

Perbaiki saya jika saya salah, tetapi saya pikir ini mungkin berfungsi untuk kueri Anda ...

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

coba npm instal setang versi 4.5.3

npm instal handlebars@4.5.3

Ini berhasil untuk saya


Ini harus menjadi komentar
Arun Vinoth

Saat ini saya menggunakan setang ekspres, versi 3.1.0
Lee Boon Kong

Terima kasih, saya sudah mencoba milik Anda dan @ mason anwser akan berhasil, tetapi saya tidak yakin mengapa ini terjadi.
Lee Boon Kong

3

Mulai dari versi 4.6.0 dan seterusnya, Setang melarang mengakses properti prototipe dan metode objek konteks secara default. Ini terkait dengan masalah keamanan yang dijelaskan di sini: https://mahmoudsec.blogspot.com/2019/04/handlebars-template-injection-and-rce.html

Rujuk ke https://github.com/wycats/handlebars.js/issues/1642

Jika Anda yakin bahwa hanya pengembang yang memiliki akses ke templat, dimungkinkan untuk mengizinkan akses prototipe dengan menginstal paket berikut:

npm i @handlebars/allow-prototype-access

Jika Anda menggunakan setang ekspres, Anda harus melanjutkan sebagai:

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

Terima kasih, ini berhasil. Jadi kita harus melakukan ini setiap kali kita harus menggunakan setang ekspres?
Yash Boura

2

Terjadi perubahan besar pada rilis Setang baru-baru ini yang menyebabkan kesalahan ini.

Anda bisa menambahkan konfigurasi yang mereka sarankan dalam dokumentasi mereka, namun waspadalah, tergantung pada implementasi Anda, ini dapat menyebabkan kerentanan terhadap serangan XXS dan 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 jadi di situlah saya menambahkan opsi, Terima kasih banyak!
Lee Boon Kong

1
Ini tidak berhasil untuk saya. Panggilan balik diharapkan, bukan objek opsi.
mrg95

0

Membuat Objek atau Array baru lain dari data yang dikembalikan oleh find() akan memecahkan masalah. Lihat di bawah ini ilustrasi sederhana

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")
});
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.