跨域SignalR组

时间:2013-02-15 08:42:58

标签: signalr

我在网站A(localhost:6599)中使用SignalR持久连接。在渲染A / index.html并连接到/ goose(我的连接名称!)时,通过SSE尊重组。将代码复制到网站B(localhost:58660)并将$ .connection更改为绝对URL(http://localhost:6599/goose)时,来自网站B的signalR客户端不会接收发送到同一组的消息。

同时,网站B可以发送消息,网站A客户端将在该组上接收消息。从组消息更改为广播,消息到达网站A和B客户端。

我在网站A上的代码:

    <div id="data"></div>

    <script>
        $(document).ready(function() {
            var connection = $.connection('/goose', "group=123", true);

            connection.start().done(function() {

                connection.received(function(data) {
                    console.log(data);
                    $("#data").html(data);
                });

                connection.send("123:hooo");
            }
            );

        });

    </script>

在服务器端:

public class GooseConnection : PersistentConnection
{
    protected override Task OnConnected(IRequest request, string connectionId)
    {
        var group = request.QueryString["group"];

        return Groups.Add(connectionId, group);
    }

    protected override Task OnReceived(IRequest request, string connectionId, string data)
    {
        // Messages are sent with the following format
        // group:message
        string[] decoded = data.Split(':');
        string groupName = decoded[0];
        string message = decoded[1];

        // Send a message to the specified
        return Groups.Send(groupName, message);
    }

    protected override Task OnDisconnected(IRequest request, string connectionId)
    {
        return Groups.Remove(connectionId, request.QueryString["group"]);
    }

}

我在网站B上的代码:

var connection = null;
        $(document).ready(function () {
            connection = $.connection('http://localhost:6599/goose', "group=123", true);

            connection.start({ jsonp: true }).done(function () {

                connection.received(function (data) {
                    console.log(data);
                    alert('oooyeah');
                    $("#data").html(data);
                });

                connection.send("123:hooo");
            }
            );

        });

        function tryagain() {
            connection.send("123:hooo");
        }

来自网站A的跟踪(抱歉格式化):

[21:31:58 GMT+0000 (GMT Standard Time)] SignalR: Negotiating with
'/goose/negotiate'. jquery.signalR-1.0.0-rc2.min.js:10 [21:31:58 GMT+0000 (GMT Standard Time)] SignalR: Attempting to connect to SSE endpoint 'http://localhost:6599/goose/connect?transport=serverSentEvents&connectionId=93b07a1b-779f-44e9-87f3-3eb201a97fdd&group=123&tid=0' jquery.signalR-1.0.0-rc2.min.js:10 [21:31:59 GMT+0000 (GMT Standard Time)] SignalR: EventSource connected jquery.signalR-1.0.0-rc2.min.js:10 [21:31:59 GMT+0000 (GMT Standard Time)] SignalR: Now monitoring keep alive with a warning timeout of 40000 and a connection lost timeout of 60000 jquery.signalR-1.0.0-rc2.min.js:10 hooo localhost:18 [21:44:30 GMT+0000 (GMT Standard Time)] SignalR: EventSource readyState: 0 jquery.signalR-1.0.0-rc2.min.js:10 [21:44:30 GMT+0000 (GMT Standard Time)] SignalR: EventSource reconnecting due to the server connection ending jquery.signalR-1.0.0-rc2.min.js:10 [21:44:32 GMT+0000 (GMT Standard Time)] SignalR: EventSource calling close() jquery.signalR-1.0.0-rc2.min.js:10 [21:44:32 GMT+0000 (GMT Standard Time)] SignalR: EventSource reconnecting

来自网站B的追踪:

[21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Auto detected cross domain url. jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Negotiating with 'http://localhost:6599/goose/negotiate'. jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: SignalR: Initializing long polling connection with server. jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Attempting to connect to 'http://localhost:6599/goose/connect?transport=longPolling&connectionId=d01cebe3-28f6-4150-a606-b9d64224edd7&group=123&tid=3' using longPolling. jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Longpolling connected jquery.signalR-1.0.0-rc2.min.js:10 [21:30:33 GMT+0000 (GMT Standard Time)] SignalR: Attempting to connect to 'http://localhost:6599/goose?transport=longPolling&connectionId=d01cebe3-28f…cloud.Spotify.Goose.Connections.GooseConnection.123%22%5D&group=123&tid=10' using longPolling. jquery.signalR-1.0.0-rc2.min.js:10 [21:32:29 GMT+0000 (GMT Standard Time)] SignalR: Attempting to connect to 'http://localhost:6599/goose?transport=longPolling&connectionId=d01cebe3-28f…acloud.Spotify.Goose.Connections.GooseConnection.123%22%5D&group=123&tid=2' using longPolling. jquery.signalR-1.0.0-rc2.min.js:10

我尝试过的事情:

  • 将自动重新连接添加到global.asax(         GlobalHost.HubPipeline.EnableAutoRejoiningGroups())
  • 手动设置.start({jsonp:true})
  • 向每个客户广播         var context = GlobalHost.ConnectionManager.GetConnectionContext();         context.Connection.Broadcast(“这是一个黑客”); 这很有效。

非常感谢任何进一步的调试建议。 安迪

2 个答案:

答案 0 :(得分:1)

您的群组问题很可能是因为当客户端重新连接时,群组不会自动重新加入。在同一域上运行时,这不是问题,因为您的客户端可能使用永远帧或服务器发送事件传输,除非底层连接存在问题,否则不会重新连接。

但是,对SignalR的跨源访问需要WebSocket或长轮询传输。考虑到您与团体有关的问题,后者可能会在您的案例中使用。 (注意:您的SignalR服务器需要在Windows 8或2012上运行.NET 4.5以支持WebSockets)。每次接收消息时,长轮询传输都必须重新连接到SignalR服务器。

要解决此问题,请添加以下内容:

public class GooseConnection : PersistentConnection
{
    protected override IEnumerable<string> OnRejoiningGroups(IRequest request, IEnumerable<string> groups, string connectionId)
    {
        return groups;
    } 
}

通过重写OnRejoiningGroups以返回groups参数而不是空集合,您允许客户端重新加入他们之前重新连接的所有组。但是,从RC2开始,SignalR不会验证重新连接的客户端是否真正在他们尝试重新加入的那些组中。只需从重新连接请求的查询字符串中提取groups参数。当然,一个行为良好的客户端只会尝试重新加入之前的组,但是在RC2上启用自动组重新加入允许攻击者将自己添加到任何组。对于许多应用程序而言,这不是问题,但这就是默认情况下未启用组重新加入的原因。

在SignalR的RTM版本中,默认情况下将启用自动组重新加入。客户端尝试重新加入的组列表也将由服务器签名,使其更加安全。

答案 1 :(得分:0)

EnableAutoRejoiningGroups是Hubs API的一项功能,由于您在较低的PersistentConnection API层工作,因此无法为您提供帮助。正如@ halter73所说,OnRejoiningGroups是在PersistentConnection层执行此操作的方法。