您的位置:澳门新葡8455最新网站 > Web前端 > 浅谈跨域以WebService对跨域的支持

浅谈跨域以WebService对跨域的支持

发布时间:2019-12-02 18:02编辑:Web前端浏览(200)

    浅谈跨域以WebService对跨域的扶助

    2015/04/03 · HTML5, JavaScript · WebService, 跨域

    原稿出处: 寒江独钓   

    跨域难点来自JavaScript的同源计谋,即只有 公约+主机名+端口号 (如存在卡塔尔(قطر‎相似,则允许互相拜见。也正是说JavaScript只好访谈和操作本人域下的能源,无法访谈和操作别的域下的能源。

    在这里前,前端和后端混杂在黄金时代道, 譬喻JavaScript直接调用同系统里面包车型客车一个Httphandler,就子虚乌有跨域的标题,不过随着当代的这种二种客商端的风靡,比如二个使用普通会有Web端,App端,以至WebApp端,种种客商端平时会采取相近套的后台管理逻辑,即API, 前后端分离的付出政策流行起来,前端只关心表现,平日选用JavaScript,后端管理逻辑和数量经常接受Web瑟维斯来提供json数据。平日的前端页面和后端的WebServiceAPI平日安插在差异的服务器可能域名上。那样,通过ajax央求Web瑟维斯的时候,就相会世同源战略的难题。

    须求验证的是,同源计谋是JavaScript里面包车型地铁限量,别的的编制程序语言,举例在C#,Java恐怕iOS等别的语言中是足以调用外界的WebService,也正是说,假设开垦Native应用,是不设有那几个难题的,可是只要开辟Web或许Html5如WebApp,平常选用JavaScript ajax对WebService发起倡议然后剖判重返的值,那样就只怕存在跨域的难点。

    貌似的,相当轻巧想到,将表面包车型客车能源搬到同二个域上就能够缓和同源计策的限量的。即在Web网址上同时支付二个Http服务端页面,全部JavaScript的号令都发到这些页面上来,那几个页面在此中使用此外语言去调用外部的WebService。即增加五个代理层。这种方法得以解决难题,但是相当不足直接和飞速。

    现阶段,比较宽泛的跨域建设方案满含JSONP (JSON with padding)和CORS (克罗斯-origin resource sharing 卡塔尔国。一些缓解方案供给客户端和服务端合营如JSOP,一些则只必要服务端合营管理比如COEnclaveS。上边分别介绍那二种跨域方案,以至服务端Web瑟维斯如何扶助那三种跨域方案。

    一、认识JSONP

    <script>成分得以作为大器晚成种Ajax传输体制:只须安装<script>成分的src属性(借使它尚未插入到document中,需求插入进去),然后浏览器就能够发送HTTP恳求下载src属性所针没有错U卡宴L。使用<script>成分举办Ajax传输的叁个主要缘由是,它不受同源计谋的震慑,因而能够使用它们从别的的服务器诉求数据,第叁个原因是含有JSON编码数据的响应心得解码。 这种利用<script>元素作为Ajax传输的技艺称为JSONP。
    若是你曾经写了三个劳动,它管理GET恳求并赶回JSON编码的数额,同源文档能够在代码中选择XMLHttpRequest和JSON.parse(卡塔尔(قطر‎。要是在服务器上启用了CO景逸SUVS,在新的浏览器下,跨域的文档也得以应用XMLHttpRequest享受到该服务。在不帮忙CO大切诺基S的旧浏览器下,跨域文书档案只通过<script>成分访谈那个服务。使用JSONP,JSON响应数据是官方的JavaScript代码,当它达到浏览器将实施它。

    JSONP以及WebService的支持

    同源战略下,有个别服务器是心余力绌赢获得服务器以外的多少,然则html里面包车型地铁img,iframe和script等标签是个不一致,这一个标签可以通过src属性央浼到其余服务器上的数量。而JSONP便是经过script节点src调用跨域的号召。

    当大家向服务器交由叁个JSONP的号召时,咱们给服务传了三个分化平日的参数,告诉服务端要对结果特别管理一下。那样服务端重返的数码就能开展一些打包,客商端就足以管理。

    比如,服务端和顾客端约定要传叁个名称为callback的参数来利用JSONP功用。比如央求的参数如下:

    JavaScript

    1
    http://www.example.net/sample.aspx?callback=mycallback

    倘诺未有前面包车型地铁callback参数,即不利用JSONP的情势,该服务的归来结果或者是二个只是的json字符串,比方:

    JavaScript

    { foo : 'bar' }

    1
    { foo : &#039;bar&#039; }

    少年老成经和服务端约定jsonp格式,那么服务端就能管理callback的参数,将重临结果开展一下拍卖,例如拍卖成:

    JavaScript

    mycallback({ foo : 'bar' })

    1
    mycallback({ foo : &#039;bar&#039; })

    能够看来,那实际上是一个函数调用,举个例子能够实今后页面定义一个名称为mycallback的回调函数:

    JavaScript

    mycallback = function(data) { alert(data.foo); };

    1
    2
    3
    4
    mycallback = function(data)
             {
                alert(data.foo);
             };

    现今,央求的重返值回去触发回调函数,那样就完了了跨域央浼。

    万一运用ServiceStack创制WebService的话,扶助Jsonp形式的调用比超级粗略,只须要在AppHost的Configure函数里面注册一下对响应结果开展过滤管理就可以。

    JavaScript

    /// <summary> /// Application specific configuration /// This method should initialize any IoC resources utilized by your web service classes. /// </summary> /// <param name="container"></param> public override void Configure(Container container) { ResponseFilters.Add((req, res, dto) => { var func = req.QueryString.Get("callback"); if (!func.isNullOrEmpty()) { res.AddHeader("Content-Type", ContentType.Html); res.Write("<script type='text/javascript'>{0}({1});</script>" .FormatWith(func, dto.ToJson())); res.Close(); } }); }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    /// &lt;summary&gt;
            /// Application specific configuration
            /// This method should initialize any IoC resources utilized by your web service classes.
            /// &lt;/summary&gt;
            /// &lt;param name=&quot;container&quot;&gt;&lt;/param&gt;
            public override void Configure(Container container)
            {
                ResponseFilters.Add((req, res, dto) =&gt;
                {
                    var func = req.QueryString.Get(&quot;callback&quot;);
                    if (!func.isNullOrEmpty())
                    {
                        res.AddHeader(&quot;Content-Type&quot;, ContentType.Html);
                        res.Write(&quot;&lt;script type=&#039;text/javascript&#039;&gt;{0}({1});&lt;/script&gt;&quot;
                            .FormatWith(func, dto.ToJson()));
                        res.Close();
                    }
                });
            }

    JSONP跨域形式相比方便,也支撑各个较老的浏览器,但是瑕疵很鲜明,他只帮忙GET的法子交给,不补助任何Post的提交,Get格局对央浼的参数长度有限制,在多少情况下大概不满足须要。所以下面就介绍一下COWranglerS的跨域应用方案。

    二、原理剖判

    同源计策下,有个别服务器是力不从心获得到服务器以外的数码,但是html里面包车型大巴img,iframe和script等标签是个例外,那一个标签可以由此src属性哀告到别的服务器上的多少。而JSONP 就是经过script节点src调用跨域的央浼。
    当我们向服务器交由三个JSONP的乞求时,大家给劳务传了贰个离奇的参数,告诉服务端要对结果非常管理一下。那样服务端重临的数量就能开展一些卷入,客商端就足以处理。
    比方。服务端和客商端约定要传二个名字为callback的参数来使用JSONP成效,比方央求的参数如下:

    http://www.example.net/sample.aspx?callback=mycallback

    若是未有前边的callback参数,即不采用JSONP的情势,该服务的归来结果大概是一个单独的json字符串,举例:{foo:'bar'}。不过只要应用JSONP形式,那么重回的是一个函数调用:mycallback({foo:'bar'}卡塔尔,那样我们在代码之中,定义一个名叫mycallback的回调函数,就能够解决跨域难题了。

    <!DOCTYPE html> 
    <html> 
    <head> 
    <meta charset="utf-8"> 
    <script src="http://code.jquery.com/jquery-1.8.0.min.js"></script> 
    <title></title> 
    <style> 
    body {
        background-color: #f3f3f3;
    }
    .main {
        width: 645px;
        margin: 30px auto;
        position: relative;
    }
    form {
        font-size: 0;
    }
    #result {
        position: absolute;
        top: 41px;
        left: -1px;
        width: 537px;
        border: 1px solid #e3e3e3;
        border-top: 0 none;
        background-color: #fff;
        padding: 0;
        color: #333;
        margin: 0;
        list-style: none;
    }
    #result li {
        line-height: 24px;
        padding-left: 12px;
    }
    #keyWords {
        width: 480px;
        padding: 10px 50px 10px 7px;
        border: 0;
        background-image: none;
        height: 20px;
        line-height: 20px;
        box-shadow: 0 1px 3px rgba(0,0,0,0.2);
        -webkit-box-shadow: 0 1px 3px rgba(0,0,0,0.2);
        -moz-box-shadow: 0 1px 3px rgba(0,0,0,0.2);
        vertical-align: middle;
        outline:none;
    } 
    #search {
        width: 104px;
        height: 40px;
        line-height: 40px;
        line-height: 37px9;
        padding: 0;
        border: 0;
        background-position: -464px -42px;
        cursor: pointer;
        color: #000;
        font-size: 16px;
        vertical-align: middle;
        outline:none;
    } 
    #search:hover {
        box-shadow: 1px 1px 3px rgba(0,0,0,0.2);
    }
    </style> 
    <script type="text/javascript"> 
    function relatedWords(data){ 
        var _html=[]; 
    
        for(var i=0;i<data.s.length;i++){
            _html.push('<li>' + data.s[i] + '</li>');
        }
    
        $('#result').html(_html.join(''));
    }; 
    
    $(function(){ 
        $('#keyWords').keyup(function() { 
            var val = $(this).val(); 
            if (val.trim() == '') {
                return ;
            }
    
            $.ajax({ 
                url:'http://suggestion.baidu.com/su?wd='+val+'&json=1&p=3&req=2&cb=relatedWords', 
                dataType:'jsonp' 
            });
        }); 
    }); 
    </script> 
    </head> 
    <body> 
    <div class="main">
        <form>
            <input type="text" id="keyWords" />
            <input type="button" id="search" value="百度一下" />
        </form>
        <ul id="result"></ul>
    </div>
    
    
    </body> 
    </html>
    

    CORS跨域及WebService的支持

    先来看二个事例,我们新建壹此中坚的html页面,在里头编写三个轻松易行的是或不是支持跨域的小本子,如下:

    XHTML

    <html xmlns="; <head> <title>AJAX跨域诉求测量检验</title> </head> <body> <input type='button' value='初阶测试' onclick='crossDomainRequest(卡塔尔(قطر‎' /> <div id="content"></div> <script type="text/javascript"> //<![CDATA[ var xhr = new XMLHttpRequest(); var url = ''; function crossDomainRequest(卡塔尔(قطر‎ { document.getElementById("content"卡塔尔.innerHTML = "开端……"; if (xhr卡塔尔(قطر‎ { xhr.open('POST', url, true卡塔尔(قطر‎; xhr.onreadystatechange = handler; xhr.send(卡塔尔(قطر‎; } else { document.getElementById("content"卡塔尔(قطر‎.innerHTML = "不能够成立 XMLHttpRequest"; } } function handler(evtXHWrangler卡塔尔(英语:State of Qatar) { if (xhr.readyState == 4卡塔尔(قطر‎ { if (xhr.status == 200卡塔尔国 { var response = xhr.responseText; document.getElementById("content"卡塔尔国.innerHTML = "结果:" + response; } else { document.getElementById("content"卡塔尔(英语:State of Qatar).innerHTML = "不相同意跨域乞请。"; } } else { document.getElementById("content"卡塔尔(قطر‎.innerHTML += "<br/>执市场价格况 readyState:" + xhr.readyState; } } //]]> </script> </body> </html>

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
      <title>AJAX跨域请求测试</title>
    </head>
    <body>
      <input type='button' value='开始测试' onclick='crossDomainRequest()' />
      <div id="content"></div>
     
      <script type="text/javascript">
        //<![CDATA[
        var xhr = new XMLHttpRequest();
        var url = 'http://localhost:8078/json/ShopUserLogin';
        function crossDomainRequest() {
          document.getElementById("content").innerHTML = "开始……";
          if (xhr) {
            xhr.open('POST', url, true);
            xhr.onreadystatechange = handler;
            xhr.send();
          } else {
            document.getElementById("content").innerHTML = "不能创建 XMLHttpRequest";
          }
        }
     
        function handler(evtXHR) {
          if (xhr.readyState == 4) {
            if (xhr.status == 200) {
              var response = xhr.responseText;
              document.getElementById("content").innerHTML = "结果:" + response;
            } else {
              document.getElementById("content").innerHTML = "不允许跨域请求。";
            }
          }
          else {
            document.getElementById("content").innerHTML += "<br/>执行状态 readyState:" + xhr.readyState;
          }
        }
        //]]>
      </script>
     
    </body>
    </html>

    下一场保留为本土html文件,能够看到,那一个本子中,对本地的劳务 发起了一个须要, 纵然使用chrome 直接展开,会看出输出的结果,不容许跨域央求。 在javascript调控台程序中相像能够看出错误提醒:

    图片 1

    那么只要在回到响应头header中注入Access-Control-Allow-Origin,那样浏览器检查评定到header中的Access-Control-Allow-Origin,则即可跨域操作了。

    相像,要是选用ServcieStack,在无数地点能够支持CORubiconS的跨域格局。最轻松易行的依然在AppHost的Configure函数里面一向写入:

    JavaScript

    /// <summary> /// Application specific configuration /// This method should initialize any IoC resources utilized by your web service classes. /// </summary> /// <param name="container"></param> public override void Configure(Container container) { this.AddPlugin(new CorsFeature()); }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /// &lt;summary&gt;
    /// Application specific configuration
    /// This method should initialize any IoC resources utilized by your web service classes.
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;container&quot;&gt;&lt;/param&gt;
    public override void Configure(Container container)
    {
        this.AddPlugin(new CorsFeature());
    }

    这么就足以了,约等于采纳暗中认可的CO大切诺基S配置:

    JavaScript

    CorsFeature(allowedOrigins:"*", allowedMethods:"GET, POST, PUT, DELETE, OPTIONS", allowedHeaders:"Content-Type", allowCredentials:false);

    1
    2
    3
    4
    CorsFeature(allowedOrigins:&quot;*&quot;,
    allowedMethods:&quot;GET, POST, PUT, DELETE, OPTIONS&quot;,
    allowedHeaders:&quot;Content-Type&quot;,
    allowCredentials:false);

    生机勃勃旦单单允许GET和POST的伸手援助CO奥迪Q3S,则只要求改为:

    JavaScript

    Plugins.Add(new CorsFeature(allowedMethods: "GET, POST"));

    1
    Plugins.Add(new CorsFeature(allowedMethods: &quot;GET, POST&quot;));

    本来也足以在AppHost的Config里面安装全局的COTiggoS,如下:

    JavaScript

    /// <summary> /// Application specific configuration /// This method should initialize any IoC resources utilized by your web service classes. /// </summary> /// <param name="container"></param> public override void Configure(Container container) { base.SetConfig(new EndpointHostConfig { GlobalResponseHeaders = { { "Access-Control-Allow-Origin", "*" }, { "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS" }, { "Access-Control-Allow-Headers", "Content-Type" }, }, }); }

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    /// &lt;summary&gt;
    /// Application specific configuration
    /// This method should initialize any IoC resources utilized by your web service classes.
    /// &lt;/summary&gt;
    /// &lt;param name=&quot;container&quot;&gt;&lt;/param&gt;
    public override void Configure(Container container)
    {
     
        base.SetConfig(new EndpointHostConfig
        {
            GlobalResponseHeaders = {
                { &quot;Access-Control-Allow-Origin&quot;, &quot;*&quot; },
                { &quot;Access-Control-Allow-Methods&quot;, &quot;GET, POST, PUT, DELETE, OPTIONS&quot; },
                { &quot;Access-Control-Allow-Headers&quot;, &quot;Content-Type&quot; },
                    },
        });
    }

    最近运作WebService,使用postman或许Chrome调用这些诉求,能够看见再次来到的值头文件中,已经增添了响应头,况且能够健康显示重返结果了:

    图片 2

    COEscortS使用起来轻便,不须要顾客端的附加管理,並且帮衬Post的措施提交伏乞,可是CO景逸SUVS的头一无二多个隐疾是对客商端的浏览器版本有需要,援救COENCORES的浏览器机器版本如下:

    图片 3

     

    总结

    正文介绍了JavaScript中的跨域基本概念和发生的由来,以至怎样消除跨域的三种方法,一种是JSONP 朝气蓬勃种是 COMuranoS,在客商端Javascript调用服务端接口的时候,假若须要接济跨域的话,供给服务端协助。JSONP的方法正是服务端对回到的值进行回调函数包装,他的亮点是扶助广大的浏览器, 短处是仅帮助Get的点子对服务端央求。另后生可畏种主流的跨域方案是COLX570S,他仅须求服务端在重回数据的时候在相应头中加入标记消息。这种措施极度方便。唯大器晚成的后天不良是急需浏览器的扶植,一些较老的浏览器恐怕不扶持CO奥迪Q5S个性。

    跨域支持是创设WebService时应有思量的二个功效点,希望本文对你在这里边面有所支持,文中是利用ServiceStack来演示跨域协理的,如若你用的WCF的话,知道跨域原理的前提下,完成跨域应该轻便。

     

    仿效资料:

    赞 收藏 评论

    图片 4

    本文由澳门新葡8455最新网站发布于Web前端,转载请注明出处:浅谈跨域以WebService对跨域的支持

    关键词: