node.js - 使用头盔更正socket.io(Web套接字)的内容安全策略

PKK*_*PKK 11 javascript websocket node.js socket.io content-security-policy

我正在尝试在节点服务器中实现内容安全策略(CSP),并且在设置socket.io时遇到问题.看起来我connectSrc在下面的代码中设置错误.有人建议设置头盔的正确方法,以便浏览器允许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
  }));
};
Run Code Online (Sandbox Code Playgroud)

这适用于所有HTTP/AJAX流量,但对于ws://协议失败.当进行socket.io连接时,我在chrome调试器中出现此错误:

Refused to connect to 'ws://localhost:3000/socket.io/1/websocket/ubexeZHZiAHwAV53WQ7u' because it violates the following Content Security Policy directive: "connect-src 'self'".
Run Code Online (Sandbox Code Playgroud)

Chrome控制台错误

Ed4*_*Ed4 22

仔细阅读内容安全策略规范解释了为什么'self'不起作用:

'self'匹配具有相同主机,端口和方案的请求.由于原始网页加载方案http://https://,'self'将不使用匹配的连接ws://.

'self'对于websocket连接来说相当无用.除非我遗漏了什么,否则我认为这是规范中的一个错误.


Kat*_*ens 8

聚会有点晚了,但我想我会在这个主题上投入一些东西。@Ed4 说得很对,'self'确实只会匹配相同的主机、端口和方案。解决它的一种方法是以一种或多种形式包含它:

connect-src: wss:- 允许连接到整个wss方案 - 基本上任何网络套接字(可能不理想)

connect-src: wss://yoursite.domain.com - 将其限制为特定端点。这是最理想的,但如果您的子域在部署之间发生变化(如我们所做的那样),则可能会受到限制

connect-src: wss://*.domain.com- 可以在那里使用通配符来加强安全性。这就是我们所做的

TL; DR - 使用通配符使事情更具体,而不仅仅是向那里的任何网络套接字开放/

参考谷歌开发者的这段话:

每个指令中的源列表是灵活的。您可以按方案(数据:,https:)指定来源,或从仅主机名(example.com,匹配该主机上的任何来源:任何方案,任何端口)到完全限定的URI(https:/ /example.com:443,仅匹配 HTTPS、仅 example.com 和仅端口 443)。接受通配符,但仅作为方案、端口或在主机名的最左侧位置::// .example.com:* 将匹配 example.com 的所有子域(但不是 example.com 本身),使用任何计划,在任何端口。

https://developers.google.com/web/fundamentals/security/csp/


Pat*_*mek 5

添加指定协议的地址为我解决了问题。

connectSources = ["'self'", "ws://localhost:3000"]
Run Code Online (Sandbox Code Playgroud)

  • 是的,我们可以这样做,但是这样就违背了“self”关键字的目的,不是吗?如果我们需要添加确切的服务器名称、端口等,那我们为什么需要这个自营业务? (8认同)