2015-09-15 5 views
1

Я экспериментирую с модулями npm в первый раз, и я пытаюсь реализовать helmet в серверном модуле для установки заголовков безопасности. Я знаю, что helmet предназначенный для Express, но я не использую Express.Как реализовать шлем в сервере узлов? [w/o Express]

Могу ли я использовать «шлем» в следующем серверном модуле? Если да, то как мне это сделать (примеры кода будут оценены)? Если нет, что я могу использовать, это будет «подключаться» к модулю ниже или я должен атаковать это по-другому?

Thx для вашей помощи/ввода.

'use strict'; 

var helmet = require('helmet') 
    , web  = require('node-static') 
    , chalk = require('chalk'); 

var server; 

module.exports = plugin; 

function plugin(options) { 
    var defaults = { 
     cache: 0 
    , port: 8080 
    , host: "localhost" 
    , verbose: false 
    }; 

    var opts = options || {}; 

    setDefaults(opts, defaults); 

    return function(files, staticsmith, done) { 
    if (server) { 
     done(); 
     return; 
    } 

    var docRoot = staticsmith.destination() 
     , fileServer = new web.Server(docRoot, { cache: opts.cache}); 

    server = require('http').createServer(function (request, response) { 

     request.addListener('end', function() { 

     fileServer.serve(request, response, function(err, res) { 

      if (err) { 
      log(chalk.red("[" + err.status + "] " + request.url), true); 

      response.writeHead(err.status, err.headers); 
      response.end("Not found"); 

      } else if (opts.verbose) { 
      log("[" + response.statusCode + "] " + request.url, true); 
      } 
     }); 

     }).resume(); 

    }).listen(opts.port, opts.host); 

    server.on('error', function (err) { 
     if (err.code == 'EADDRINUSE') { 
     log(chalk.red("Address " + opts.host + ":" + opts.port + " already in use")); 
     throw err; 
     } 
    }); 

    log(chalk.green("serving " + docRoot + " at http://" + opts.host + ":" + opts.port)); 
    done(); 
    }; 

    function setDefaults(opts, defaults) { 
    Object.keys(defaults).forEach(function(key) { 
     if (!opts[key]) { 
     opts[key] = defaults[key]; 
     } 
    }); 
    } 

    function formatNumber(num) { 
    return num < 10 ? "0" + num : num; 
    } 

    function log(message, timestamp) { 
    var tag = chalk.blue("[staticsmith-serve]"); 
    var date = new Date(); 
    var tstamp = formatNumber(date.getHours()) + ":" + formatNumber(date.getMinutes()) + ":" + formatNumber(date.getSeconds()); 
    console.log(tag + (timestamp ? " " + tstamp : "") + " " + message); 
    } 
} 

ответ

1

Лучшим решением было реализовать Security Headers политику, не используя каких-либо-рода «промежуточного слоя». Это упрощает, чище и безопаснее на сервере, не полагаясь на другой модуль разработчиков.

Для этого я создал security-config.json5 файл, который содержит настройки, что делает его легко поддерживать и обновлять:

module.exports = { 
    security: [ 
    { name: 'Cache-Control', 
     value: 'public, max-age=30672000' 
    }, 
    { name: 'server', 
     value: 'mySpecial-Server' 
    }, 
    { name: 'Strict-Transport-Security', 
     value: 'max-age=86400' 
    }, 
    { name: 'X-Content-Type-Options', 
     value: 'nosniff' 
    }, 
    { name: 'X-Frame-Options', 
     value: 'DENY' 
    }, 
    { name: 'X-Powered-By', 
     value: 'Awesomeness' 
    }, 
    { name: 'X-XSS-Protection', 
     value: '1; mode=block' 
    }, 
    { name: 'Content-Security-Policy', 
     value: "default-src 'none'; script-src 'self' https://cdnjs.cloudflare.com connect-src 'self'; img-src 'self' data:; style-src 'self' https://cdnjs.cloudflare.com; font-src 'self' https://cdnjs.cloudflare.com; manifest-src 'self'" 
    } 
    ] 
}; 

Приведенные выше настройки являются хорошей отправной точкой, обратив особое внимание на кавычки для Content-Security-Policy ключ/значение, но вы можете сделать некоторые настройки для своего сайта. Я также показываю, как реализовать CDN здесь.

Теперь в вашей createServer() функции вы можете цикл через в пар ключ: значение и добавьте их в заголовки с помощью setHeader():

var security_default = require('./security-config.json5'); 

for(let i = 0; i < security_default.security.length; i++) { 
    res.setHeader(
    security_default.security[i].name, 
    security_default.security[i].value 
); 
} 

Модуль Helmet Узел по НПМ является большим, но это раздутый (требует 3 МБ дискового пространства) и требует регулярного обновления, пока этот метод светлый (< 850bytes), подключаемый и поддерживаемый для тех, кто не хочет использовать промежуточное программное обеспечение.