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

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

初稿出处:
寒江独钓   

跨域难点来自JavaScript的同源计策,即唯有 协议+主机名+端口号
(如存在)同样,则允许相互拜访。也正是说JavaScript只可以访问和操作本人域下的能源,不能够访问和操作其余域下的能源。

在原先,前端和后端混杂在一块,
比方JavaScript直接调用同系统里面包车型地铁五个Httphandler,就不设有跨域的主题素材,可是随着当代的这种各样客户端的盛行,譬如多少个用到一般会有Web端,App端,以及WebApp端,各样客户端平常会采取一样套的后台管理逻辑,即API,
前后端分离的支出政策流行起来,前端只关怀呈现,平日使用JavaScript,后端管理逻辑和数量一般选取WebService来提供json数据。一般的前端页面和后端的WebServiceAPI平常计划在区别的服务器或许域名上。那样,通过ajax须求WebService的时候,就能冒出同源计策的题目。

内需申明的是,同源战略是JavaScript里面包车型客车限制,其余的编制程序语言,比方在C#,Java只怕iOS等别的语言中是足以调用外部的WebService,也正是说,若是开辟Native应用,是不存在这一个难题的,可是一旦开辟Web也许Html5如WebApp,经常选拔JavaScript
ajax对WebService发起呼吁然后深入分析再次来到的值,那样就可能存在跨域的难点。

貌似的,很轻巧想到,将表面包车型大巴财富搬到同二个域上就能够减轻同源战略的范围的。即在Web网站上还要费用多少个Http服务端页面,全部JavaScript的伸手都发到这些页面上来,那么些页面在中间接选举择此外语言去调用外界的WebService。即加多七个代理层。这种措施得以减轻难点,可是相当不够直接和飞跃。

眼前,相比较普及的跨域消除方案包含JSONP (JSON with
padding)和CORS (Cross-origin
resource sharing
)。一些减轻方案必要客户端和服务端合作如JSOP,一些则只须要服务端协作管理举例CORubiconS。上边分别介绍那二种跨域方案,以及劳动端Web瑟维斯怎么着援救那三种跨域方案。

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

澳门凯旋门注册网址跨域问题来源于JavaScript的同源策略。{ foo : &#澳门凯旋门注册网址跨域问题来源于JavaScript的同源策略。039;bar&#澳门凯旋门注册网址跨域问题来源于JavaScript的同源策略。039; }

1
{ foo : 'bar' }

一旦和服务端约定jsonp格式,那么服务端就能够处理callback的参数,将再次来到结果举行一下管理,例如拍卖成:

JavaScript

mycallback({ foo : 'bar' })

1
mycallback({ foo : 'bar' })

能够看到,那实际是一个函数调用,比方能够兑未来页面定义贰个名称为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=&#澳门凯旋门注册网址跨域问题来源于JavaScript的同源策略。039;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方式对央浼的参数长度有限定,在稍微情况下或然不知足必要。所以上面就介绍一下CORAV4S的跨域消除方案。

CORS跨域及WebService的支持

先来看三个例证,大家新建三个主干的html页面,在其间编写一个简易的是不是协理跨域的小本子,如下:

XHTML

澳门凯旋门注册网址跨域问题来源于JavaScript的同源策略。<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(evtXH凯雷德) { 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>

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,在非常的多地方可以援救COTiggoS的跨域情势。最简便易行的照旧在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());
}

诸如此类就可以了,也就是选择私下认可的COENCORES配置:

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的央浼援助COQX56S,则只供给改为:

JavaScript

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

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

自然也足以在AppHost的Config里面安装全局的CO途乐S,如下:

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

CO猎豹CS6S使用起来轻便,没有要求客户端的附加管理,而且辅助Post的主意交给央求,不过COENCORES的唯一三个缺陷是对客户端的浏览器版本有必要,帮衬COPRADOS的浏览器机器版本如下:

澳门凯旋门注册网址 3

 

总结

正文介绍了JavaScript中的跨域基本概念和产生的原由,以及怎么样缓和跨域的二种办法,一种是JSONP
一种是
CO奥迪Q5S,在客户端Javascript调用服务端接口的时候,假若急需辅助跨域的话,必要服务端协理。JSONP的艺术正是服务端对回到的值进行回调函数包装,他的帮助和益处是支撑广大的浏览器,
缺点是仅帮忙Get的方法对服务端须要。另一种主流的跨域方案是COWranglerS,他仅须要服务端在回来数据的时候在对应头中到场标记新闻。这种艺术充足省事。唯一的弱点是急需浏览器的支撑,一些较老的浏览器或然不协理CO安德拉S天性。

跨域援救是开创WebService时应当思考的二个功用点,希望本文对您在那边面有所扶助,文中是利用ServiceStack来演示跨域支持的,假如您用的WCF的话,知道跨域原理的前提下,完毕跨域应该轻巧。

 

参考资料:

赞 收藏
评论

澳门凯旋门注册网址 4

相关文章