zoukankan      html  css  js  c++  java
  • 一步一步学习SignalR进行实时通信_3_通过CORS解决跨域

    一步一步学习SignalR进行实时通信_3_通过CORS解决跨域

    标签(空格分隔): SignalR


    前言

    这周工作比较忙,一直没有时间学习SignalR,大致希望一周能写一篇关于SignalR的文章。上一篇用Persistent Connections方式实现了个简单的在线聊天功能,这次我们继续深入学习。

    关于start()的补充

    在上一篇文章里前台的html页面我们通过几句javascript创建了一个,代码如下,也可以下载上次的源码。

    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <title>persistent connections</title>
        <script src="Scripts/jquery-1.10.2.min.js"></script>
        <script src="Scripts/jquery.signalR-2.0.0.min.js"></script>
    </head>
    <body>
        <h1>Echo service</h1>
        <div>
            <input type="text" id="text" />
            <button id="send">Send</button>
        </div>
        <script>
            $(function () {
                var connection = $.connection("/echo");
                connection.logging = true;
                connection.received(function (data) {
                    $("body").append(data + "<br />");
                });
                connection.error(function (err) {
                    alert("存在一个错误. 
    " +
                                "Error: " + err.message);
                });
                connection.start().done(function () {
                    $("#send").click(function () {
                        connection.send($("#text").val());
                        $("#text").val("").focus();
                    });
                });
            });
        </script>
    </body>
    </html>
    

    这里需要做些说明:通过代码var connection = $.connection("/echo");
    我们创建了一个连接,通过connection.start().done()来开启连接并在连接完成时处理我们需要处理的事件。
    如果你将以下代码

    connection.start().done(function () {
        connection.send('Hi');
    });
    

    分成2部分写,如:

    connection.start();
    connection.send('Hi');
    

    那么你必须注意:
    虽然你在connection.send()之前调用了connection.start()开启了连接,但是connection.start()是一个__异步__方法,意味着有可能你在调用connection.send()时connection并未开启,那么项目将会报错。
    正确方法如之前代码所示,再加上一段开启失败的代码:

    var connection = $.connection("/echo");
    connection.start(function() {
        // 连接开启成功才会进入这里
        connection.send("Hi");
    }).fail(function() {
        //连接开启失败则进入这里
        alert("服务开启失败");
    });
    

    跨域解决方案

    上篇文章里有同学问到跨域的问题,那么在接下来的时间我将会带着大家一起学习。
    在SignalR解决跨域,有两种方式:第一种是JSONP,第二种是CORS。

    JSONP

    如果你的服务必须要支持老版本的浏览器,那么JSONP是唯一选择,否则处于安全的考虑这并不被推荐,具体什么安全因素我并不知晓(有同学知道的话可以说明下),基于快速学习的情况下,我们无需纠缠于此。服务器默认会禁用此功能,我们可以通过初始化时提供一个ConnectionConfiguration对象并设置EnableJSONP属性为true来激活此功能。

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            var config = new ConnectionConfiguration()
            {
                EnableJSONP = true
            };
            app.MapSignalR<EchoConnection>("/echo", config);
        }
    }
    

    我想这几句代码应该很好理解,我们在前面提到过MapSignalR<TConnection>()有许多重载方法,这是另一个重载方法通过提供一个ConnectionConfiguration对象进行相关配置。

    CORS

    CORS是一个独立的框架,它可以很方便的解决跨域问题,通过Nuget安装
    安装命令:Install-Package microsoft.owin.cors
    CORS是通过Owin实现的,所以我们需要在项目启动时对他进行一些配置,和做SignalR映射一样实在Startup中进行配置。

    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            //app.MapSignalR<EchoConnection>("/echo");
            app.Map("/echo", 
                map => {
                           map.UseCors(CorsOptions.AllowAll);
                           map.RunSignalR<EchoConnection>();
                       }
            );
        }
    }
    

    代码应该也不难,这次我们通过app.Map()进行映射,第一个参数是映射的地址,第二个参数是一个lambda表达式,通过UseCors(CorsOptions.AllowAll)允许允许跨域。

    CORS跨域演示

    JSONP我不做演示了有兴趣的可以自己尝试下,接下来我这里做一个通过CORS来进行跨域聊天。首先我讲上次的项目复制一份,省得再重新打代码,并将__复制__出来的项目名称由__SignalR_1__改为__SignalR_2_CORS__。
    项目目录如下图所示:

    省得麻烦,我把SignalR_1部署在IIS上面,这就充当了 一个远程的SignalR服务。

    部署成功后,如图所示:

    此时我们讲SignalR_2_CORS项目稍作修改

    1. 将Startup中的映射删去,此时SignalR_2_CORS已不做SignalR服务器了,只做客户端来连接SignalR_1提供的服务
    2. 将echo中的var connection = $.connection("/echo");改为
      var connection = $.connection("http://127.0.0.1:8083/echo");

      然后运行SignalR_2_CORS中的echo页面,结果如图所示:

      出现了一个错误,这个错误提示是我们自己写的

      因为我们的__SignalR_1__并没有允许跨域连接,那么在__SignalR_2_CORS__中当然无法连接,接下来我们在项目一中允许跨域连接。

      重新编译项目一后再刷新下__SignalR_1__的_echo.html_页面,注意我们这个页面地址

      然后刷新下__SignalR_2_CORS__的页面,注意这个地址

      连接成功,没有报错了,发送个消息试试看(●ˇ∀ˇ●)

    结束语

    这里通过CORS实现了SignalR的跨域问题,跨域如此简单赶快试试吧 。

    注意:在通过Nuget安装CORS包时,我这边提示了Unable to find package 'Microsoft.AspNet.Cors'我已经翻墙了,所以这个应该不是需要翻墙才能下载,但是在Nuget页面中搜索确实有这个包,具体什么原因引起的我也不清楚,如果你有碰到这个问题请下载解压并添加引用即可,由于Microsoft.AspNet.Cors依赖于Microsoft.AspNet.Cors,所以里面的2个包都要添加引用

    源码下载
    本文发布至作业部落

    参考文献

    SignalR Programming in Microsoft ASP.NET pdf 下载

  • 相关阅读:
    linux ftp启用和停用及vsftpd安装 ssh 启用和停用命令及ssh的安装
    linux 网络命令
    printf的使用
    Shell echo命令
    shell脚本之文件操作
    shell脚本之字符串运算的使用
    linux的计划任务操作
    系统操作有关的命令
    shell脚本之 operater.sh 算术运算符;比较运算符;布尔运算符;逻辑与或非运算符;字符串运算符的使用
    shell脚本的参数传递使用
  • 原文地址:https://www.cnblogs.com/Jack-Blog/p/4735199.html
Copyright © 2011-2022 走看看