【问题标题】:how to set socket.io origins to restrict connections to one url如何设置 socket.io 来源以限制连接到一个 url
【发布时间】:2013-03-24 04:50:13
【问题描述】:

我们有一个 html 网站和一个为该网站提供服务的 node.js 服务器。 网站和服务器使用 socke.io 交换数据。 我们在文档中发现了这一点:

来源默认为 *:* 允许连接到 Socket.IO 服务器的源。

我们的 html.site 位于 http://questionexample.com/page1 上。 只有这个网站可以连接到我们的服务器。(但每个人都可以连接到那个网站。) 我们如何设置原点?

【问题讨论】:

    标签: javascript node.js socket.io


    【解决方案1】:

    对于较新版本的 socket.io(直到当前的 4.x.x,您需要将 CORS 来源设置为服务器选项的一部分。

    CORS 现在被拆分为自己的模块 - 有关详细信息,请参阅 readme

    默认配置是;

    {
      "origin": "*",
      "methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
      "preflightContinue": false,
      "optionsSuccessStatus": 204
    }
    

    并限制在一个站点上使用任何子域;

    cors: {
            origin: [/\.example\.com$/],
            methods: ["GET", "POST"]
            }
    

    这是一个非常简单/基本的配置块,适合那些不使用 express 或除了原始 socket.io 引擎之外的任何东西的人; 编辑:更新了 socket.io 的第 3 版。

    // Options for socket.io => 3.0.0
    var options = {
            allowUpgrades: true,
            transports: [ 'polling', 'websocket' ],
            pingTimeout: 9000,
            pingInterval: 3000,
            cookie: 'mycookie',
            httpCompression: true,
            cors: '*:*' <---- Allow any origin here [NOTE THE NAME CHANGE]
    };
    

    旧版本使用;

    // Options for socket.io > 1.0.0
    var options = {
            allowUpgrades: true,
            transports: [ 'polling', 'websocket' ],
            pingTimeout: 9000,
            pingInterval: 3000,
            cookie: 'mycookie',
            httpCompression: true,
            origins: '*:*' <---- Allow any origin here
    };
    
    io = require('socket.io')(8010, options);
    

    【讨论】:

      【解决方案2】:

      你可以在服务器端使用你网站的 url 做这样的事情

        if (origin !== 'https://foo.example.com') {
          return callback('origin not allowed', false);
        }
        callback(null, true);
      });
      

      【讨论】:

        【解决方案3】:

        如果你深入研究 Socket.io 源代码,你会发现这样几行:

        var origin = request.headers.origin || request.headers.referer
          , origins = this.get('origins');
        
        ...
        
        var parts = url.parse(origin);
        parts.port = parts.port || 80;
        var ok =
          ~origins.indexOf(parts.hostname + ':' + parts.port) ||
          ~origins.indexOf(parts.hostname + ':*') ||
          ~origins.indexOf('*:' + parts.port);
        

        如您所见,Socket.io 获取来自客户端的源(或引用者),检索域名和端口, 并与您指定的origins 选项进行比较。

        所以有效的origins 值是(* 表示“任何”):

        • testsite.com:80
        • http://testsite.com:80
        • http://*:8080
        • *:8080
        • testsite.com:* http://someotherdomain.com:8080 (以空格分隔的多个来源)
        • testsite.com:*/somepath (socket.io 将忽略 /somepath)
        • *:*

        而且这些都是无效的(因为没有端口号):

        • testsite.com
        • http://testsite.com
        • http://testsite.com/somepath

        另请注意,如果您将sub.testsite.com 指定为来源值,则testsite.com 将是有效来源。

        【讨论】:

          【解决方案4】:

          我也遇到过类似的问题。 尝试在生产模式下运行节点NODE_ENV=production node app.js。 我有那个代码(as recommended here):

          io.configure('production', function(){
              console.log("Server in production mode");
              io.enable('browser client minification');  // send minified client
              io.enable('browser client etag'); // apply etag caching logic based on version number
              io.enable('browser client gzip'); // the file
              io.set('log level', 1);           // logging
              io.set('transports', [            // all transports (optional if you want flashsocket)
                  'websocket'
                  , 'flashsocket'
                  , 'htmlfile'
                  , 'xhr-polling'
                  , 'jsonp-polling'
              ]);
          io.set('origins', 'http://questionexample.com/page1:*');
          });
          

          并且 Node 在开发模式下运行,所以它根本无法工作。启用生产模式后一切正常。

          我知道答案有点晚了,但也许其他人会使用它

          【讨论】:

            【解决方案5】:

            我认为io.set('origins', http://questionexample.com/page1) 应该这样做

            【讨论】:

            • 感谢您的回答,但这对我们不起作用。当我们加载网站但无法连接时,我们会收到以下警告:illegal origin
            • 你想接受什么?我认为来源是客户端的IP。为了安全起见,您建议的来源限制也不起作用,因为可以轻松更改网址。您可能想看看客户的Authorisation
            • 你也需要一个端口号
            • io.set 在最新版本中不再受支持。 config 在服务器上运行 var socket = require('socket.io')({ // options go here });
            • 更改为 io.origins(['https://foo.example.com:443']);io.origins((origin, callback) =&gt; { if (origin !== 'https://foo.example.com') { return callback('origin not allowed', false); } callback(null, true); }); 请参阅:new-Server-httpServer-options
            猜你喜欢
            • 2019-01-26
            • 1970-01-01
            • 1970-01-01
            • 2018-02-21
            • 1970-01-01
            • 2016-10-24
            • 1970-01-01
            • 1970-01-01
            • 2016-10-03
            相关资源
            最近更新 更多