3

我正在创建一个示例 Express 应用程序来演示 Content-Security-Policy (CSP) 标头,并尝试使用helmet-csp

头盔 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 标头:

内容安全策略:frame-src 'none'

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

内容安全策略:frame-src 'self'

每当我需要/想要在每个路由的基础上自定义由helmet-csp 设置的标头时,我是否需要在每个路由中手动覆盖它们app.get,例如:

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

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

4

2 回答 2

9

此行为内置于 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,所以如果您有任何反馈,请告诉我!)

于 2017-06-13T16:43:48.810 回答
6

自定义中间件可以更改标头,只需在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);
});
于 2017-06-13T13:39:19.220 回答