在各个路线上实施helmet-csp

时间:2017-06-13 03:22:39

标签: node.js express content-security-policy helmet.js

我正在创建一个示例Express应用,以演示内容安全策略(CSP)标头,并尝试使用helmet-csp

helmet-csp的所有文档都显示它通过app.use(csp({ ... }))用作标准的第三方中间件 - 这会将CSP标头添加到我的应用程序中的每条路由中,但我想要在个别路线上进行自定义。

示例应用

var express = require('express');
var http = require('http');
var csp = require('helmet-csp');
var app = express();

app.use(csp({
    directives: {
        frameSrc: ["'none'"]
    }
}));

app.get('/', (request, response) => {
    response.send('hi, :wave: =]');
});

app.get('/frameable', (request, response) => {
    response.send('you can frame me!');
});

http.createServer(app).listen(80, (err) => {
    if (err) {
        return console.log('error', err);
    }
});

通过上述内容,每条路由都会收到CSP标头:

  

Content-Security-Policy:frame-src'none'

/frameable路由中,我希望将此CSP标头覆盖为:

  

Content-Security-Policy:frame-src'self'

每当我需要/想要在每个路由的基础上自定义由head-csp设置的标头时,我是否需要在每个app.get内使用以下行来手动覆盖它们:

response.setHeader('Content-Security-Policy', "frame-src 'self'");

或者有没有办法通过helmet-csp本身来做到这一点?

2 个答案:

答案 0 :(得分:3)

自定义中间件可以更改标题,只需在use(csp)

之后添加即可
app.use(function (req, res, next) {
    if (req.url == '/frameable') {
        res.set('Content-Security-Policy', 'frame-src \'self\'');
    }
    next();
});

您也可以链接中间件,因为它是一个返回函数的函数:

app.use(function (req, res, next) {
    var middleware;

    if (req.url == '/frameable') {
        middleware = csp({
            directives: {
                frameSrc: ["'self'"]
            }
        });
    } else {
        middleware = csp({
            directives: {
                frameSrc: ["'none'"]
            }
        });
    }

    middleware(req, res, next);
});

答案 1 :(得分:3)

此行为内置于Express。

Express允许您为每个路由指定多个请求处理程序。因为csp返回路由处理程序,所以可以在 路由处理程序之前添加它:

app.get('/frameable', csp({
    directives: {
        frameSrc: ["'self'"]
    }
}), (request, response) => {
    response.send('you can frame me!');
});

如果你想稍微分开一些东西,你可以这样做:

var normalCspHandler = csp({
    directives: {
        frameSrc: ["'none'"]
    }
});

var frameSelfCspHandler = csp({
    directives: {
        frameSrc: ["'self'"]
    }
});

app.use(normalCspHandler);

app.get('/frameable', frameSelfCspHandler, (request, response) => {
    response.send('you can frame me!');
});

(顺便说一句,我保留了Helmet,如果您有任何反馈,请告诉我!)