Possiamo implementare un token di sicurezza per i form in Node.js con relativa semplicità.
Useremo MongoDB per le sessioni e i seguenti package:
npm install express-session --save
npm install connect-mongodb-session --save
npm install helmet --save
Creiamo una classe helper per la codifica e la verifica del token:
'use strict';
const crypto = require('crypto');
class Security {
static md5(value) {
if(!value) {
return;
}
return crypto.createHash('md5').update(value).digest('hex');
}
static isValidNonce(value, req) {
return (value === this.md5(req.sessionID + req.headers['user-agent']));
}
}
module.exports = Security;
Quindi definiamo la nostra app:
'use strict';
const express = require('express');
const bodyParser = require('body-parser');
const port = process.env.PORT || 8080;
const session = require('express-session');
const MongoDBStore = require('connect-mongodb-session')(session);
const helmet = require('helmet');
const app = express();
const Security = require('./lib/Security');
const store = new MongoDBStore({
uri: 'mongodb://localhost:27017/db'
collection: 'sessions'
});
app.disable('x-powered-by');
app.set('view engine', 'ejs');
app.set('env', 'development');
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(helmet());
app.use(session({
secret: 'stringa segreta',
resave: false,
saveUninitialized: true,
store: store,
unset: 'destroy',
name: 'nome-cookie'
}));
// Routes
if (app.get('env') === 'development') {
app.use((err, req, res, next) => {
res.status(err.status || 500);
});
}
app.use((err, req, res, next) => {
res.status(err.status || 500);
});
app.listen(port);
Nella route del nostro form creiamo il token e lo passiamo alla view:
// Routes
app.get('/contact', (req, res) => {
res.render('contact', {nonce: Security.md5(req.sessionID + req.headers['user-agent'])});
});
Quindi inseriamo il token nella view:
<form action="/contact" method="post">
<!-- campi del form -->
<input type="hidden" name="nonce" value="<%= nonce %>">
</form>
Infine validiamo il token:
app.post('/contact', (req, res) => {
if(Security.isValidNonce(req.body.nonce, req)) {
//...
} else {
// Errore
}
});