根据我对Content Security Policy的理解,nonce必须根据每个请求进行更改。这意味着(我认为)它必须在运行时在客户端生成,而不是在Webpack配置的构建时生成。我在我的应用中测试了the webpack_nonce functionality,效果很好。
不幸的是,我不确定如何将在客户端上运行时生成的值转换为实际的CSP策略,该策略在index.html文件中设置为元标记(或某些等效标记) )或在服务器本身。
我想您可以在客户端上动态设置CSP元标记,但这似乎是一种安全风险。我已经尝试了csp-webpack-plugin,它在构建时计算文件的哈希值,然后将它们添加到index.html。这个过程对我来说很有意义,它只是不支持我们的用例。
我只是觉得我错过了使用webpack_nonce的东西。
答案 0 :(得分:3)
我们能够通过让webpack构建我们的索引页面(例如通过HtmlWebpackPlugin)作为模板然后动态地提供它来获得动态的随机数。这样,您可以将__webpack_nonce__
设置为类似<%=nonce%>
的插值表达式,并且服务器视图引擎可以在页面加载时以动态随机数为单位。例如,如果您使用快递:
Webpack配置:
const HtmlWebpackPlugin = require('html-webpack-plugin')
module.exports = {
entry: 'index.js',
output: {
path: __dirname + '/dist',
filename: 'index_bundle.js'
},
plugins: [
new HtmlWebpackPlugin({
filename: __dirname + '/dist/index.ejs',
})
]
}
Webpack入口点(index.js):
__webpack_nonce__ = '<%=nonce%>';
快递应用:
// Generate dynamic nonce on each request cycle
const uuid = require('node-uuid');
app.use((req, res, next) => {
res.locals.nonce = uuid.v4();
next();
});
app.set('view engine', 'ejs');
app.route('/').get((req, res, next) => {
res.render('path/to/index.ejs', { nonce: res.locals.nonce });
});
注入的<script>
代码会附加文字属性nonce=<%=nonce%>
,然后服务器会在为您的网页投放时进行插值。
请注意,如果您使用带有HtmlWebpackPlugin的自定义模板,您可能需要为ejs
设置不同的插值分隔符,否则Webpack将在构建时而不是运行时插入nonce表达式。
快递应用:
const ejs = require('ejs);
ejs.delimiter = '?'; // Means instead use __webpack_nonce__ = '<?=nonce?>'