SignalR 2.0 CORS Chrome禁用Web安全性奇怪的行为

 手机用户2602920905 发布于 2023-02-13 09:22

我正在努力让CORS与SignalR 2.0.0一起工作 - 我知道有很多关于它的SO帖子,我一直在仔细研究它们.

我在Chrome中使用已禁用的网络安全功能进行测试时遇到了一个问题,希望有人可以解释.

我有两个独立的MVC5站点(单独的解决方案)在IIS Express(不同的端口)上运行.其中一个是主机服务器,它安装了SignalR.该Startup.cs主机看起来是这样的:

public void Configuration(IAppBuilder app)
        {
            app.Map("/signalr", map =>
            {
                map.UseCors(CorsOptions.AllowAll);
                var hubConfiguration = new HubConfiguration
                {
                   // EnableJSONP = true                    
                   // EnableDetailedErrors = true                                     
                };
                map.RunSignalR(hubConfiguration);
            });
        }

我只用一个方法在主机上有一个集线器.另一个MVC5站点是客户端,它具有以下JavaScript:

jQuery的1.10.2.min.js

jquery.signalR-2.0.0.min.js

主机 MVC站点上对〜/ signalr/hubs JavaScript的引用

它调用的JS是以下(非常标准):

$.connection.hub.logging = true;
var chat = $.connection.chatHub;

    chat.client.broadcastMessage = function (name, message) {
        var encodedName = $('
').text(name).html(); var encodedMsg = $('
').text(message).html(); $('#discussion').append('
  • ' + encodedName + ':  ' + encodedMsg + '
  • '); }; $('#displayname').val(prompt('Enter your name:', '')); $('#message').focus(); $.connection.hub.url = 'http://localhost:60601/signalr'; // <-- pointing to the host MVC5 site $.connection.hub.start().done(function () { console.log("Connected, transport = " + $.connection.hub.transport.name); $('#sendmessage').click(function () { chat.server.send($('#displayname').val(), $('#message').val()); $('#message').val('').focus(); }); }).fail(function (data) { console.log('[Hub Start FAILED]' + data); });

    编辑发布日志

    当我使用上面的代码时,我的主机站点上没有错误.在客户端站点上,我在Chrome DevTools控制台中收到以下错误:

    [18:06:41 GMT-0600 (Central Standard Time)] SignalR: Auto detected cross domain url. 
    [18:06:41 GMT-0600 (Central Standard Time)] SignalR: Client subscribed to hub 'chathub'.
    [18:06:41 GMT-0600 (Central Standard Time)] SignalR: Negotiating with 'http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3'.
    MLHttpRequest cannot load http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3&_=1386201997462. The 'Access-Control-Allow-Origin' header contains the invalid value 'http://localhost:50709, *'. Origin 'http://localhost:50709' is therefore not allowed access.
    SignalR error: Error: Error during negotiation request.
    [18:06:41 GMT-0600 (Central Standard Time)] SignalR: Stopping connection.
    

    如果我通过添加参数来改变客户端javascript中集线器的启动$.connection.hub.start({ jsonp: true, transport: 'webSockets' })(如果我没有指定webSockets作为传输,那么SignalR成功使用longpolling传输),那么我得到以下错误日志.

    客户端(Chrome DevTools控制台)

    [18:06:41 GMT-0600 (Central Standard Time)] SignalR: Auto detected cross domain url. 
    [18:06:41 GMT-0600 (Central Standard Time)] SignalR: Client subscribed to hub 'chathub'.
    [18:12:16 GMT-0600 (Central Standard Time)] SignalR: Negotiating with 'http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3'
    [18:12:17 GMT-0600 (Central Standard Time)] SignalR: Connecting to websocket endpoint 'ws://localhost:60601/signalr/connect?transport=webSockets&connectionToken=GzcGbVs35BV0AFtJ2%2BJQqEYlQfW6ejf6CJ8QI73zfG8OsonD0LIzDmtzNBWM6jSHiD0ptuStjmyOKTpszMFJOgVZoBLuYN08TYx1WUbdNqKDLRZ35Vozmk666%2F7x3rjgowmXhTjX0pVlx8nDY%2FWrpA%3D%3D&connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&tid=4'
    [18:12:17 GMT-0600 (Central Standard Time)] SignalR: Websocket opened.
    [18:12:22 GMT-0600 (Central Standard Time)] SignalR: webSockets timed out when trying to connect.
    [18:12:22 GMT-0600 (Central Standard Time)] SignalR: Closing the Websocket.
    SignalR error: Error: No transport could be initialized successfully. Try specifying a different transport or none at all for auto initialization.
    [18:12:22 GMT-0600 (Central Standard Time)] SignalR: Stopping connection.
    [18:12:22 GMT-0600 (Central Standard Time)] SignalR: Fired ajax abort async = true. 
    

    和主机端(在VS2013输出窗口中):

    SignalR.Transports.TransportHeartBeat Information: 0 : Connection 3e856309-8396-481e-8d32-b4085a93985f is New.
    SignalR.Transports.WebSocketTransport Information: 0 : CloseSocket(3e856309-8396-481e-8d32-b4085a93985f)
    SignalR.Transports.TransportHeartBeat Verbose: 0 : 3e856309-8396-481e-8d32-b4085a93985f is dead
    SignalR.Transports.WebSocketTransport Information: 0 : Abort(3e856309-8396-481e-8d32-b4085a93985f)
    SignalR.Transports.TransportHeartBeat Information: 0 : Removing connection 3e856309-8396-481e-8d32-b4085a93985f
    SignalR.Transports.WebSocketTransport Information: 0 : End(3e856309-8396-481e-8d32-b4085a93985f)
    SignalR.Transports.WebSocketTransport Verbose: 0 : DrainWrites(3e856309-8396-481e-8d32-b4085a93985f)
    SignalR.Transports.WebSocketTransport Information: 0 : CompleteRequest (3e856309-8396-481e-8d32-b4085a93985f)
    

    问题

    我在Chrome禁用网络安全模式下启动主机网站,而客户端网站通常在Chrome中启动,我仍然收到CORS错误,连接被删除.

    我在Chrome禁用网络安全模式启动客户端网站,主机网站通常在Chrome中启动,我遇到没有CORS问题,连接效果很好.

    (如果两个网站都在Chrome禁用的网络安全模式下运行,那么效果很好,但这并不奇怪)

    问题

    当主机的安全性被禁用而客户端没有安全时,我希望不会遇到任何CORS问题 - 而不是相反.为什么会这样?

    1 个回答
    • 问题似乎与你的Access-Control-Allow-Origin标题有关.

      map.UseCors(CorsOptions.AllowAll);
      

      以上行应该使SignalR CORS请求的每个响应都具有以下标头:

      Access-Control-Allow-Origin: (request origin)
      

      在您的情况下,(请求源)应该是http://localhost:50709,但它是http://localhost:50709, *由以下日志输出判断:

      [18:06:41 GMT-0600 (Central Standard Time)] SignalR: Negotiating with 'http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3'.
      HTMLHttpRequest cannot load http://localhost:60601/signalr/negotiate?connectionData=%5B%7B%22name%22%3A%22chathub%22%7D%5D&clientProtocol=1.3&_=1386201997462.
      The 'Access-Control-Allow-Origin' header contains the invalid value 'http://localhost:50709, *'. Origin 'http://localhost:50709' is therefore not allowed access.
      SignalR error: Error: Error during negotiation request.
      

      这很可能是由web.config中的类似内容引起的:

      <httpProtocol>
           <customHeaders>
               <add name="Access-Control-Allow-Origin" value="*" />
           </customHeaders>
      </httpProtocol>
      

      或者在您的中间件代码中使用类似于以下内容的内容:

      Response.AppendHeader("Access-Control-Allow-Origin", "*");
      

      无论哪种方式,因为您已经在使用,所以map.UseCors(CorsOptions.AllowAll);不应该在Access-Control-Allow-Origin其他地方设置标题.

      关于JSONP的注意事项

      最后,我知道你可能只是出于调试目的而这样做,但是像这样开始连接:$.connection.hub.start({ jsonp: true, transport: 'webSockets' })可能不是最好的主意.

      使用这些设置,协商请求(以及任何长轮询请求)将始终使用JSONP而不是CORS.当你无法使CORS工作时,这可能是有意义的,但是如果你可以使用CORS,你应该使用它而不是启用JSONP,因为CORS允许更精细的访问控制配置.

      如果EnableJSONP在服务器上设置为true,则允许在任何网站上运行的JS代码访问您的SignalR服务,无论您设置的CorsOptions是什么.

      如果您决定在服务器上启用JSONP,则没有理由jsonp: true在传递给配置对象时指定,hub.start因为如果CORS请求失败,SignalR应该回退并尝试使用JSONP.

      指定也是如此transport: 'webSockets'.默认情况下,如果可用,SignalR将首先尝试使用WebSocket传输.

      2023-02-13 09:28 回答
    撰写答案
    今天,你开发时遇到什么问题呢?
    立即提问
    热门标签
    PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
    Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有