it-swarm.com.de

Übergeben Sie in ExpressJS Variablen an JavaScript

Ich bin völlig verloren damit; Ich benutze NodeJS, um eine JSON abzurufen, und ich muss die Variable an meine Seite übergeben, damit JavaScript die Daten verwendet.

app.get('/test', function(req, res) {
    res.render('testPage', {
        myVar: 'My Data'
    });

Das ist mein Express-Code (sehr einfach für Testzwecke); Jetzt mit EJS möchte ich diese Daten sammeln, von denen ich weiß, dass sie auf der Seite dargestellt werden sollen

<%= myVar %>

Aber ich muss in der Lage sein, diese Daten in JavaScript zu sammeln (wenn möglich in einer JS-Datei), aber jetzt, um nur die Variable in einer Alert-Box anzuzeigen, habe ich es versucht

In Jade ist es wie alert('!{myVar}') oder !{JSON.stringify(myVar)}. Kann ich in EJS etwas Ähnliches machen? Ich brauche kein Feld wie <input type=hidden> und nehme den Wert des Feldes in Javascript. Wenn jemand helfen kann, werde ich sehr geschätzt

35
Jetson John

Sie könnten dies (clientseitig) verwenden:

<script>
  var myVar = <%- JSON.stringify(myVar) %>;
</script>

Sie können EJS auch dazu bringen, eine .js-Datei zu rendern:

app.get('/test.js', function(req, res) {
  res.set('Content-Type', 'application/javascript');
  res.render('testPage', { myVar : ... });
});

Die Vorlagendatei (testPage) muss jedoch noch die Erweiterung .html haben. Andernfalls wird sie von EJS nicht gefunden (es sei denn, Sie teilen Express mit).

@Ksloan weist in den Kommentaren darauf hin, dass Sie darauf achten müssen, was myVar enthält. Wenn der Inhalt benutzergenerierte Inhalte enthält, kann Ihre Site für Skriptinjektionsangriffe offen bleiben.

Eine mögliche Lösung, um dies zu verhindern:

<script>
  function htmlDecode(input){
    var e = document.createElement('div');
    e.innerHTML = input;
    return e.childNodes.length === 0 ? "" : e.childNodes[0].nodeValue;
  }
  var myVar = JSON.parse(htmlDecode("<%= JSON.stringify(myVar) %>"));
</script>
63
robertklep

Die Hauptschwierigkeit besteht hier darin, XSS-Risiken zu vermeiden, wenn myVar Anführungszeichen oder </script> enthält. Um dieses Problem zu vermeiden, schlage ich vor, Base64 coding nach JSON.stringify zu verwenden. Dadurch werden alle Risiken in Bezug auf Anführungszeichen oder HTML-Tags vermieden, da Base64 nur "sichere" Zeichen enthält, um eine Anführungszeichenfolge einzugeben.

Die Lösung, die ich vorschlage:

EJS-Datei:

<script>
  var myVar = <%- passValue(myVar) %>
</script>

was in etwas gerendert wird (zum Beispiel hier myVar = null):

<script>
  var myVar = JSON.parse(Base64.decode("bnVsbA=="))
</script>

Serverseitiger NodeJS:

function passValue(value) {
  return 'JSON.parse(Base64.decode("' + new Buffer(JSON.stringify(value)).toString('base64') + '"))'
}

Clientseitiger JS (Dies ist eine Implementierung von Base64-Decodierung, die mit Unicode funktioniert. Sie können eine andere verwenden, wenn Sie dies vorziehen, aber seien Sie vorsichtig, wenn sie Unicode unterstützt)

var Base64={_keyStr:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",encode:function(e){var t="";var n,r,i,s,o,u,a;var f=0;e=Base64._utf8_encode(e);while(f<e.length){n=e.charCodeAt(f++);r=e.charCodeAt(f++);i=e.charCodeAt(f++);s=n>>2;o=(n&3)<<4|r>>4;u=(r&15)<<2|i>>6;a=i&63;if(isNaN(r)){u=a=64}else if(isNaN(i)){a=64}t=t+this._keyStr.charAt(s)+this._keyStr.charAt(o)+this._keyStr.charAt(u)+this._keyStr.charAt(a)}return t},decode:function(e){var t="";var n,r,i;var s,o,u,a;var f=0;e=e.replace(/[^A-Za-z0-9\+\/\=]/g,"");while(f<e.length){s=this._keyStr.indexOf(e.charAt(f++));o=this._keyStr.indexOf(e.charAt(f++));u=this._keyStr.indexOf(e.charAt(f++));a=this._keyStr.indexOf(e.charAt(f++));n=s<<2|o>>4;r=(o&15)<<4|u>>2;i=(u&3)<<6|a;t=t+String.fromCharCode(n);if(u!=64){t=t+String.fromCharCode(r)}if(a!=64){t=t+String.fromCharCode(i)}}t=Base64._utf8_decode(t);return t},_utf8_encode:function(e){e=e.replace(/\r\n/g,"\n");var t="";for(var n=0;n<e.length;n++){var r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r)}else if(r>127&&r<2048){t+=String.fromCharCode(r>>6|192);t+=String.fromCharCode(r&63|128)}else{t+=String.fromCharCode(r>>12|224);t+=String.fromCharCode(r>>6&63|128);t+=String.fromCharCode(r&63|128)}}return t},_utf8_decode:function(e){var t="";var n=0;var r=c1=c2=0;while(n<e.length){r=e.charCodeAt(n);if(r<128){t+=String.fromCharCode(r);n++}else if(r>191&&r<224){c2=e.charCodeAt(n+1);t+=String.fromCharCode((r&31)<<6|c2&63);n+=2}else{c2=e.charCodeAt(n+1);c3=e.charCodeAt(n+2);t+=String.fromCharCode((r&15)<<12|(c2&63)<<6|c3&63);n+=3}}return t}}

Versuche dies:

<script type="text/javascript">
     window.addEventListener('load', function(){
         alert('<%= myVar %>');
     });
</script>
3
karaxuna

wenn Sie komplexere Objekte wie ein Array haben, können Sie Folgendes tun:

<% if (myVar) { %>
   <script>
      myVar = JSON.parse('<%- JSON.stringify(myVar) %>');
   </script>
<% } %>

andernfalls funktionieren vorherige Lösungen, die Sie gesehen haben, nicht

2

Hier, wie ich es funktionierte, ___ im Knoten js den Json so weitergeben

let j =[];
//sample json
j.Push({data:"hi});

res.render('index',{json:j});

jetzt in js funktion

var json = JSON.parse('<%- JSON.stringify(json) %>');

Das hat gut für mich funktioniert

1
Jerin A Mathews

In der akzeptierten Lösung schlägt JSON.parse fehl, wenn myVar eine Eigenschaft mit einem Wert mit nicht verdecktem Anführungszeichen hat. Also besser traverseObj und entkommen Sie jede String-Eigenschaft.

Hier ist eine Funktion, die meinen Fall abdeckt:

function traverseObj (obj, callback)
{
    var result = {};
    if ( !isArray(obj) && !isObject(obj) ) {
         return callback(obj);
    }

    for ( var key in obj ) {
        if ( obj.hasOwnProperty(key) ) {
            var value = obj[key];
            if (isMongoId(value)){
                var newValue = callback(value.toString());
                result[key] = newValue;
            }
            else if (isArray ( value) ) {
                var newArr = [];
                for ( var i=0; i < value.length; i++ ) {
                    var arrVal = traverseObj(value[i], callback);
                    newArr.Push(arrVal);
                }
                result[key] = newArr;
            }
            else if ( isObject(value) ) {
                result[key] = traverseObj(value, callback);
            }
            else {
                var newValue = callback(value);
                result[key] = newValue;
            }
        }
    }
    return result;
};

In ejs muss man einfach: 

<%
    var encodeValue = function(val) {
        if ( typeof val === 'string' ) {
            return sanitizeXSS(val); //use some library (example npm install xss)
        }
        return val;
    }

    var encodedProduct = ejs_utils.traverseObj(product, encodeValue);
%>

und jetzt können Sie transportieren mit sicherer Syntax

window.product = <%-JSON.stringify(encodedProduct)%>;
0
user732456

Per Dokumentation hier :

Gehen Sie zu Latest Release , laden Sie ./ejs.js oder ./ejs.min.js herunter.

Fügen Sie eine davon auf Ihrer Seite und ejs.render(str) ein.

0
spitz