2015-03-11 4 views
8

sto usando nodejs e di solito tramandare CSRF token di come le seguenti:Passando token CSRF di reagire/FLUX dal nodo

util.js

module.exports.csrf = function csrf(req, res, next){ 
    res.locals.token = req.csrfToken(); 
    next(); 
}; 

app.js

app.use(csrf()); 
app.use(util.csrf); 

e poi nella pagina ejs avrei fatto

<input type="hidden" name="_csrf" value="<%= token %>"> 

Tuttavia, ora sto usando flux/react per il mio front end e ho bisogno di passare un token csrf per l'invio di un modulo e non sono sicuro di come farlo. C'è stata una risposta simile qui utilizzando giada:

How to implement CSRF protection in Ajax calls using express.js (looking for complete example)?

Tuttavia, sto usando ejs (con JSX) (o solo html) e non si vuole utilizzare giada

+0

Facendo eco Joel, mi piacerebbe davvero suggerire facendo questo in un al di fuori di reagire. Sono affezionato al modo in cui il servizio '$ http' di Angular gestisce questo cercando un cookie di sessione, incluso quello su ogni richiesta XHR in uscita. –

risposta

-3

Passando attraverso la roba template in React è un po 'complicato. Potrebbe essere meglio impostare semplicemente una chiamata Ajax per il token CSRF.

This link dettagli come farlo con Django e jQuery, ma i concetti dovrebbero essere abbastanza portabili.

+1

https://github.com/pillarjs/understanding-csrf#exposing-your-csrf-token-via-ajax – williamcotton

7

Ho trovato che il modo migliore per farlo in React è aggiungere il token csrf a un negozio o passarlo al contesto del componente.

Si può vedere come è stato fatto modificando leggermente il Yahoo Fluxible react-router example.

context.executeAction(setTokenAction, req.csrfToken(), function(){}); 

Questo esegue un'azione flusso con la csrf token come parametro. L'architettura flusso Yahoo serializza i valori del negozio al cliente tramite:

var exposed = 'window.App=' + serialize(app.dehydrate(context)) + ';';

Questo viene scritto verso la pagina in un tag script, che possono poi essere consultato sul nella javascript client-side. Sarà simile a questa:

<script> 
window.App = { 
  context: { 
    dispatcher: { 
      stores: { 
        ApplicationStore: { 
          csrf: "1234abcd", 
        } 
      } 
    } 
  } 
}; 
</script> 

Here is the Html.jsx component in the Flux example.

Se non si sta creando un'applicazione isomorfo (i componenti reagiscono vengono eseguiti sul sever così come il client), allora vorrei suggerire solo scrivere un tag script che contiene il token csrf.

Per Fluxible tale valore è quindi rehydrated on the client.

var dehydratedState = window.App; // Sent from the server 
var app = require('./app'); 

app.rehydrate(dehydratedState, function (err, context) { 
    ... 
}); 

lasciando con un negozio popolata sul client senza un ulteriore richiesta HTTP. È quindi possibile accedere al token csrf da qualsiasi luogo accedendo al negozio.

È possibile passare tramite il contesto facendo qualcosa di simile:

var componentContext = context.getComponentContext(); 
componentContext.csrf = req.csrfToken(); 

... 

var markup = React.renderToString(Component({context: componentContext})) 

È quindi possibile accedervi tramite oggetti di scena del componente.

this.props.context.csrf

Se si utilizza Fluxible e vuole passare tramite il contesto avrei forse farlo in un plugin, ma si ottiene l'idea.

codice sever completa:

/** 
* Copyright 2014, Yahoo! Inc. 
* Copyrights licensed under the New BSD License. See the accompanying LICENSE file for terms. 
*/ 
require('babel/register'); 
var express = require('express'); 
var favicon = require('serve-favicon'); 
var serialize = require('serialize-javascript'); 
var navigateAction = require('./actions/navigate'); 
var setCsrfTokenAction = require('./actions/setCsrfToken'); 
var debug = require('debug')('Example'); 
var React = require('react'); 
var app = require('./app'); 
var HtmlComponent = React.createFactory(require('./components/Html.jsx')); 
var Router = require('react-router'); 

var server = express(); 
server.use(favicon(__dirname + '/../favicon.ico')); 
server.use('/public', express.static(__dirname + '/build')); 

server.use(function (req, res, next) { 
    var context = app.createContext(); 

    debug('Executing navigate action'); 
    Router.run(app.getComponent(), req.path, function (Handler, state) { 
     context.executeAction(setCsrfTokenAction, req.csrfToken(), function(){}); 
     context.executeAction(navigateAction, state, function() { 
      debug('Exposing context state'); 
      var exposed = 'window.App=' + serialize(app.dehydrate(context)) + ';'; 

      debug('Rendering Application component into html'); 
      var Component = React.createFactory(Handler); 
      var html = React.renderToStaticMarkup(HtmlComponent({ 
       state: exposed, 
       markup: React.renderToString(Component({context:context.getComponentContext()})) 
      })); 

      debug('Sending markup'); 
      res.send(html); 
     }); 
    }); 
}); 

var port = process.env.PORT || 3000; 
server.listen(port); 
console.log('Listening on port ' + port);