您的位置:奥门新浦京网址 > Wed前段 > 浅谈跨域以WebService对跨域的支持,你该知道的字

浅谈跨域以WebService对跨域的支持,你该知道的字

发布时间:2019-11-12 05:23编辑:Wed前段浏览(99)

    总结

    本文介绍了JavaScript中的跨域基本概念和产生的原因,以及如何解决跨域的两种方法,一种是JSONP 一种是 CORS,在客户端Javascript调用服务端接口的时候,如果需要支持跨域的话,需要服务端支持。JSONP的方式就是服务端对返回的值进行回调函数包装,他的优点是支持众多的浏览器, 缺点是仅支持Get的方式对服务端请求。另一种主流的跨域方案是CORS,他仅需要服务端在返回数据的时候在相应头中加入标识信息。这种方式非常简便。唯一的缺点是需要浏览器的支持,一些较老的浏览器可能不支持CORS特性。

    跨域支持是创建WebService时应该考虑的一个功能点,希望本文对您在这边面有所帮助,文中是使用ServiceStack来演示跨域支持的,如果您用的WCF的话,知道跨域原理的前提下,实现跨域应该不难。

     

    Verdana

    无衬线字体,优点在于它在小字上仍结构清晰端整、阅读辨识容易。

    四、环境变量

    JavaScript 允许在函数体内部,引用当前环境的其他变量。

    var f = function () { console.log(x); };

    1
    2
    3
    var f = function () {
      console.log(x);
    };

    上面代码中,函数体里面使用了变量x。该变量由运行环境提供。

    现在问题就来了,由于函数可以在不同的运行环境执行,所以需要有一种机制,能够在函数体内部获得当前的运行环境(context)。所以,this就出现了,它的设计目的就是在函数体内部,指代函数当前的运行环境。

    var f = function () { console.log(this.x); }

    1
    2
    3
    var f = function () {
      console.log(this.x);
    }

    上面代码中,函数体里面的this.x就是指当前运行环境的x

    var f = function () { console.log(this.x); } var x = 1; var obj = { f: f, x: 2, }; // 单独执行 f() // 1 // obj 环境执行 obj.f() // 2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    var f = function () {
      console.log(this.x);
    }
     
    var x = 1;
    var obj = {
      f: f,
      x: 2,
    };
     
    // 单独执行
    f() // 1
     
    // obj 环境执行
    obj.f() // 2

    上面代码中,函数f在全局环境执行,this.x指向全局环境的x

    图片 1

    obj环境执行,this.x指向obj.x

    图片 2

    回到本文开头提出的问题,obj.foo()是通过obj找到foo,所以就是在obj环境执行。一旦var foo = obj.foo,变量foo就直接指向函数本身,所以foo()就变成在全局环境执行。

    1 赞 4 收藏 评论

    图片 3

    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(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>

    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控制台程序中同样可以看到错误提示:

    图片 4

    那么如果在返回响应头header中注入Access-Control-Allow-Origin,这样浏览器检测到header中的Access-Control-Allow-Origin,则就可以跨域操作了。

    同样,如果使用ServcieStack,在很多地方可以支持CORS的跨域方式。最简单的还是在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());
    }

    这样就可以了,相当于使用默认的CORS配置:

    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的请求支持CORS,则只需要改为:

    JavaScript

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

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

    当然也可以在AppHost的Config里面设置全局的CORS,如下:

    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调用这个请求,可以看到返回的值头文件中,已经加上了响应头,并且可以正常显示返回结果了:

    图片 5

    CORS使用起来简单,不需要客户端的额外处理,而且支持Post的方式提交请求,但是CORS的唯一一个缺点是对客户端的浏览器版本有要求,支持CORS的浏览器机器版本如下:

    图片 6

     

    Times New Roman

    Mac 平台 Safari 下默认的英文字体,是最常见且广为人知的西文衬线字体之一,众多网页浏览器和文字处理软件都是用它作为默认字体。

    二、内存的数据结构

    JavaScript 语言之所以有this的设计,跟内存里面的数据结构有关系。

    var obj = { foo: 5 };

    1
    var obj = { foo:  5 };

    上面的代码将一个对象赋值给变量obj。JavaScript 引擎会先在内存里面,生成一个对象{ foo: 5 },然后把这个对象的内存地址赋值给变量obj

    图片 7

    也就是说,变量obj是一个地址(reference)。后面如果要读取obj.foo,引擎先从obj拿到内存地址,然后再从该地址读出原始的对象,返回它的foo属性。

    原始的对象以字典结构保存,每一个属性名都对应一个属性描述对象。举例来说,上面例子的foo属性,实际上是以下面的形式保存的。

    图片 8

    { foo: { [[value]]: 5 [[writable]]: true [[enumerable]]: true [[configurable]]: true } }

    1
    2
    3
    4
    5
    6
    7
    8
    {
      foo: {
        [[value]]: 5
        [[writable]]: true
        [[enumerable]]: true
        [[configurable]]: true
      }
    }

    注意,foo属性的值保存在属性描述对象的value属性里面。

    参考资料:

    赞 收藏 评论

    图片 9

    2、西文在前,中文在后

    由于大部分中文字体也是带有英文部分的,但是英文部分又不怎么好看,同理英文字体中大多不包含中文。

    所以通常会先进行英文字体的声明,选择最优的英文字体,这样不会影响到中文字体的选择,中文字体声明则紧随其次。

    一、问题的由来

    学懂 JavaScript 语言,一个标志就是理解下面两种写法,可能有不一样的结果。

    var obj = { foo: function () {} }; var foo = obj.foo; // 写法一 obj.foo() // 写法二 foo()

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    var obj = {
      foo: function () {}
    };
     
    var foo = obj.foo;
     
    // 写法一
    obj.foo()
     
    // 写法二
    foo()

    上面代码中,虽然obj.foofoo指向同一个函数,但是执行结果可能不一样。请看下面的例子。

    var obj = { foo: function () { console.log(this.bar) }, bar: 1 }; var foo = obj.foo; var bar = 2; obj.foo() // 1 foo() // 2

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    var obj = {
      foo: function () { console.log(this.bar) },
      bar: 1
    };
     
    var foo = obj.foo;
    var bar = 2;
     
    obj.foo() // 1
    foo() // 2

    这种差异的原因,就在于函数体内部使用了this关键字。很多教科书会告诉你,this指的是函数运行时所在的环境。对于obj.foo()来说,foo运行在obj环境,所以this指向obj;对于foo()来说,foo运行在全局环境,所以this指向全局环境。所以,两者的运行结果不一样。

    这种解释没错,但是教科书往往不告诉你,为什么会这样?也就是说,函数的运行环境到底是怎么决定的?举例来说,为什么obj.foo()就是在obj环境执行,而一旦var foo = obj.foofoo()就变成在全局环境执行?

    本文就来解释 JavaScript 这样处理的原理。理解了这一点,你就会彻底理解this的作用。

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

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

    原文出处: 寒江独钓   

    跨域问题来源于JavaScript的同源策略,即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。

    在以前,前端和后端混杂在一起, 比如JavaScript直接调用同系统里面的一个Httphandler,就不存在跨域的问题,但是随着现代的这种多种客户端的流行,比如一个应用通常会有Web端,App端,以及WebApp端,各种客户端通常会使用同一套的后台处理逻辑,即API, 前后端分离的开发策略流行起来,前端只关注展现,通常使用JavaScript,后端处理逻辑和数据通常使用WebService来提供json数据。一般的前端页面和后端的WebService API通常部署在不同的服务器或者域名上。这样,通过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,一些则只需要服务端配合处理比如CORS。下面分别介绍这两种跨域方案,以及服务端WebService如何支持这两种跨域方案。

    Consolas

    这是一套等宽的字体,属无衬线字体。这个字体使用了微软的 ClearType 字型平滑技术,主要是设计做为代码的显示字型之用,特别之处是它的“0”字加入了一斜撇,以方便与字母“O”分辨。

    ClearType:由微软在其操作系统中提供的屏幕亚像素微调字体平滑工具,让 Windows 字体更加漂亮。在 Windows XP 平台上,这项技术默认是关闭,到了Windows Vista 才默认为开启。

    图片 10

    上图是 Github 代码区块的字体设置,可以看到,默认字体就是 Consolas ,紧接着的几个都是其它等宽字体,如果用户的系统中都没有预装这些字体,则会匹配最后一个 monospace ,它表示等宽字体系列,会从用户系统中的等宽字体中选取一个展示。

    JavaScript 的 this 原理

    2018/06/19 · JavaScript · this

    原文出处: 阮一峰   

    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方式对请求的参数长度有限制,在有些情况下可能不满足要求。所以下面就介绍一下CORS的跨域解决方案。

    字体定义顺序

    字体定义顺序是一门学问,通常而言,我们定义字体的时候,会定义多个字体或字体系列。举个栗子:

    body { font-family: tahoma, arial, 'Hiragino Sans GB', '5b8b4f53', sans-serif; }

    1
    2
    3
    body {
        font-family: tahoma, arial, 'Hiragino Sans GB', '5b8b4f53', sans-serif;
    }

    别看短短 5 个字体名,其实其中门道很深。解释一下:

    1. 使用 tahoma 作为首选的西文字体,小字号下结构清晰端整、阅读辨识容易;
    2. 用户电脑未预装 tohoma,则选择 arial 作为替代的西文字体,覆盖 windows 和 MAC OS;
    3. Hiragino Sans GB 为冬青黑体,首选的中文字体,保证了 MAC 用户的观看体验;
    4. Windows 下没有预装冬青黑体,则使用 ‘5b8b4f53’ 宋体为替代的中文字体方案,小字号下有着不错的效果;
    5. 最后使用无衬线系列字体 sans-serif 结尾,保证旧版本操作系统用户能选中一款电脑预装的无衬线字体,向下兼容。

    嗯,其实上面的 font-family 就是淘宝首页 body 的字体定义,非常的规范,每一个字体的定义都有它的意义。

    图片 11

    三、函数

    这样的结构是很清晰的,问题在于属性的值可能是一个函数。

    var obj = { foo: function () {} };

    1
    var obj = { foo: function () {} };

    这时,引擎会将函数单独保存在内存中,然后再将函数的地址赋值给foo属性的value属性。

    图片 12

    { foo: { [[value]]: 函数的地址 ... } }

    1
    2
    3
    4
    5
    6
    {
      foo: {
        [[value]]: 函数的地址
        ...
      }
    }

    由于函数是一个单独的值,所以它可以在不同的环境(上下文)执行。

    var f = function () {}; var obj = { f: f }; // 单独执行 f() // obj 环境执行 obj.f()

    1
    2
    3
    4
    5
    6
    7
    8
    var f = function () {};
    var obj = { f: f };
     
    // 单独执行
    f()
     
    // obj 环境执行
    obj.f()

    4、兼顾旧操作系统,以字体族系列 serif 和 sans-serif 结尾

    当使用一些非常新的字体时,要考虑向下兼容,兼顾到一些极旧的操作系统,使用字体族系列 serif 和sans-serif 结尾总归是不错的选择。

    到此本文结束,如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。


    开本系列,谈谈一些有趣的 CSS 题目,题目类型天马行空,想到什么说什么,不仅为了拓宽一下解决问题的思路,更涉及一些容易忽视的 CSS 细节。

    解题不考虑兼容性,题目天马行空,想到什么说什么,如果解题中有你感觉到生僻的 CSS 属性,赶紧去补习一下吧。

    不断更新,不断更新,不断更新,重要的事情说三遍。

    所有题目汇总在我的 Github 。

    • 有趣的CSS题目(1): 左边竖条的实现方法
    • 有趣的CSS题目(2): 从条纹边框的实现谈盒子模型
    • 有趣的CSS题目(3): 层叠顺序与堆栈上下文知多少
    • 有趣的CSS题目(4): 从倒影说起,谈谈 CSS 继承 inherit
    • 有趣的CSS题目(5): 单行居中,两行居左,超过两行省略
    • 有趣的CSS题目(6): 全兼容的多列均匀布局问题
    • 有趣的CSS题目(7):消失的边界线问题
    • 有趣的CSS题目(8):纯CSS的导航栏Tab切换方案
    • 有趣的CSS题目(9):巧妙实现 CSS 斜线
    • 有趣的CSS题目(10):结构性伪类选择器
    • 有趣的CSS题目(11):reset.css 知多少?

    打赏支持我写出更多好文章,谢谢!

    打赏作者

    fantasy 、cuisive

    fantasy和 cuisive 字体在浏览器中不常用,在各个浏览器中有明显的差异。

    字体定义的细节

    其他一些小细节也很重要,譬如定义字体的时候,何时需要在字体两端添加引号?像这样:

    p{ font-family: 'Microsoft YaHei', '黑体-简', '5b8b4f53'; }

    1
    2
    3
    p{
        font-family: 'Microsoft YaHei', '黑体-简', '5b8b4f53';
    }

    当字体名字中间有空格,中文名字体及 Unicode 字符编码表示的中文字体,为了保证兼容性,都建议在字体两端添加单引号或者双引号。

    3、兼顾多操作系统

    选择字体的时候要考虑多操作系统。例如 MAC OS 下的很多中文字体在 Windows 都没有预装,为了保证 MAC 用户的体验,在定义中文字体的时候,先定义 MAC 用户的中文字体,再定义 Windows 用户的中文字体;

    本文由奥门新浦京网址发布于Wed前段,转载请注明出处:浅谈跨域以WebService对跨域的支持,你该知道的字

    关键词:

上一篇:没有了

下一篇:没有了