在个别路线上实施 helmet-csp

Implement helmet-csp on individual routes

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

helmet-csp 的所有文档显示它通过 app.use(csp({ ... })) 作为标准 third-party-middleware 使用 - 这将 CSP header 添加到 每个 路线在我的应用程序中,但我想在个别路线上自定义它。

示例应用程序

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 header:

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

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

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

每当我 need/want 在 per-route 的基础上自定义 helmet-csp 设置的 header 时,我是否需要在每个 app.get 中手动覆盖它们用这样一行:

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

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

一个自定义中间件可以改变headers,只需在use(csp)

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

您还可以链接中间件,因为它是一个函数 returns 一个函数:

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);
});

此行为内置于 Express 中。

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

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