node.js – 使用头盔修正socket.io(web套接字)的内容安全策略
我试图在节点服务器中实现内容安全策略(CSP),并且在设置socket.io时遇到困难。 它看起来像我在下面的代码中设置不正确的connectSrc
。 有人可以build议正确的方式来设置头盔,以便浏览器允许Web套接字连接吗? 提前致谢!
我正在使用头盔模块生成CSP; 以下是设置CSP的代码:
securitySetup = function(app) { var connectSources, helmet, scriptSources, styleSources; helmet = require("helmet"); app.use(helmet()); app.use(helmet.hidePoweredBy()); app.use(helmet.noSniff()); app.use(helmet.crossdomain()); scriptSources = ["'self'", "'unsafe-inline'", "'unsafe-eval'", "ajax.googleapis.com"]; styleSources = ["'self'", "'unsafe-inline'", "ajax.googleapis.com"]; connectSources = ["'self'"]; return app.use(helmet.contentSecurityPolicy({ defaultSrc: ["'self'"], scriptSrc: scriptSources, styleSrc: styleSources, connectSrc: connectSources, reportUri: '/report-violation', reportOnly: false, setAllHeaders: false, safari5: false })); };
这适用于所有HTTP / AJAXstream量,但对ws://协议失败。 在socket.io连接时,在chromedebugging器中出现这个错误:
Refused to connect to 'ws://localhost:3000/socket.io/1/websocket/ubexeZHZiAHwAV53WQ7u' because it violates the following Content Security Policy directive: "connect-src 'self'".
用指定的协议添加地址解决了我的问题。
connectSources = ["'self'", "ws://localhost:3000"]
仔细阅读内容安全策略规范解释了为什么'self'
不起作用:
'self'
使用相同的主机,端口和scheme匹配请求。 由于您的原始页面使用schemehttp://
或https://
, 'self'
加载,将不会使用ws://
匹配连接。
这使得'self'
对websocket连接而言毫无用处。 除非我错过了一些东西,我认为这是规范中的一个错误。
你可以使用ws:或者wss:as关键字作为websocket,这里是我的代码使用
app.use(helmet.csp({ 'default-src': ["'self'"], 'connect-src': [ "'self'" , "blob:", 'wss:', 'websocket.domain', ], 'font-src': ["'self'",'s3.amazonaws.com',"maxcdn.bootstrapcdn.com"], 'img-src': ["'self'", 'data:'], 'style-src': ["'self'","maxcdn.bootstrapcdn.com",'s3.amazonaws.com',"'unsafe-inline'"], 'script-src': ["'self'","'unsafe-inline'","'unsafe-eval'",'blob:'], reportOnly: false, setAllHeaders: false, safari5: false }))
与wss://websocket.domain是websocket的域名,所以如果你可以使用它的本地主机
晚会晚了,但认为我会在这个问题上投入一些东西。 @ Ed4是相当正确的, 'self'
确实只能匹配相同的主机,端口和scheme。 解决方法是将其包含在一个或多个表单中:
connect-src: wss:
– 允许连接到整个wss
scheme – 基本上任何 web套接字(可能都不是理想的)
connect-src: wss://yoursite.domain.com
– 将其限制为特定的端点。 这是最理想的,但是如果你的子域在部署之间改变(如我们的那样)
connect-src: wss://*.domain.com
– 可以使用通配符来提高安全性。 这就是我们所做的
TL; DR – 使用通配符使事情更具体,而不需要打开自己的网站,
请参阅Google开发者的这段话:
每个指令中的源列表是灵活的。 您可以通过scheme(data :, https :)指定源,或者仅从主机名(example.com,匹配该主机上的任何源:任何scheme,任何端口)到特定URI( https: /example.com:443 ,仅匹配HTTPS,仅匹配example.com,仅匹配443端口)。 通配符被接受,但只作为scheme,端口或主机名的最左边位置:// .example.com:*将匹配example.com的所有子域(但不是example.com本身),使用任何计划,在任何港口。
https://developers.google.com/web/fundamentals/security/csp/
这是一种自动添加当前主机和端口的方式(es6语法):
import csp from 'helmet-csp'; app.use((req, res, next) => { let wsSrc = (req.protocol === 'http' ? 'ws://' : 'wss://') + req.get('host'); csp({ connectSrc: ['\'self\'', wsSrc], })(req, res, next); });