我正在创建一个示例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本身来做到这一点?
答案 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,如果您有任何反馈,请告诉我!)