同源策略与JS跨域请求(图文实例详解)

同源策略与跨域
跨域请求解决方案

同源策略与跨域

首先,我们看一个例子(以 ASP.NET MVC 为例 )

  1. 在index视图页中,使用Jquery AJAX方式请求Controller Action方法。(同源请求,一切正常

    这里写图片描述

  2. 在本地新建一个 html文件,使用Jquery AJAX方式请求 位于 IIS EXPRESS 上的方法。(浏览器拦截跨域请求

    这里写图片描述

在例子中,涉及到了一个重要的概念——同源策略(Same-Origin Policy)。所谓的 同源 是指域名、协议、端口号 相同。不同的客户端脚本(javascript,ActionScript)在没有授权的情况下,不能读取对方资源。简单来说,浏览器允许包含在页面A的脚本访问第二个页面B的数据资源,这一切是建立在A和B页面是同源的基础上。

同源策略

同源策略 是由Netscape提出的一个著名的安全策略,现在所有支持JavaScript 的浏览器都会使用这个策略。实际上,这种策略只是一个规范,并不是强制要求,各大厂商的浏览器只是针对同源策略的一种实现。它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。

跨域与跨域请求

跨域 简单的来说,指的是两个资源非同源。出于安全方面的考虑,页面中的JavaScript在请求非同源的资源时就会出 跨域问题 ——即跨域请求,这时,由于同源策略,我们的请求会被浏览器禁止。也就出现了 我们常说的 跨域 问题。

下面,我们看一下,具体哪些情况会出现跨域问题(具体策略限制):

这里写图片描述

主流跨域请求解决方案

JSONP 实现跨域

为了便于客户端使用数据,逐渐形成了一种非正式传输协议。人们把它称作JSONP。该协议的一个要点就是允许用户传递一个callback参数给服务端,然后服务端返回数据时会将这个callback参数作为函数名来包裹住JSON数据,这样客户端就可以随意定制自己的函数来自动处理返回数据了。

jsonp的核心是动态添加 script标签 来调用服务器提供的js脚本。

备注:详细的解释,可以看一下这篇文章,超级详细说说JSON和JSONP

JSONP实现原理?

1、JS 跨域请求资源会被限制。但是在页面中,script 标签跨域时,却是没有限制的(frame,img同理)。
2、我们通过,script的src属性,请求服务器,并通过参数(如:?callback=foo,foo为本地一个执行的方法)告诉服务器返回指定格式的JS脚本,并将数据封装在此脚本中。
3、服务器再配合客户端返回一段脚本 (如:* foo({“id”: 123, “name” : 张三, “age”: 17});* ),其实返回的就是 一个客户端本地的一个 可执行的方法的方法名, 并将要返回的 数据封装在了参数 里。
4、请求到资源后,本地就会执行此方法,通过对参数的处理,也就获取到了我们所要的数据。

具体实现

  1. 客户端
p><input id="btn3" type="button" name="name" value="AJAXGET2_Param" onclick="AJAXRequest('/Test/AnotherFunc', 'GET', { 'request': 'wys' }, 'jsonp')"/></p>

<script>
var ServerUrl = 'http://localhost:33268';
//TODO:  封装 公用方法
    //AJAX 请求
    function AJAXRequest(url, type, data, dataType) {
        $.ajax({
            url: ServerUrl+url,
            type: type,
            data: data,
            dataType: dataType,
            jsonpCallback: foo,
            success: function (data) {
                console.log(data.staus);
            },
            error: function (err) {
                alert('错误信息:' + err);
            }
        });
    }
</script>

2.服务器

  public string AnotherFunc(string request)
        {
            string str = "foo({\"staus\":\"world\"})";
            return  str;
        }

3.运行结果

这里写图片描述

4.注意事项

  1. 服务器返回数据的格式
    是返回的JSONP格式,而不是单纯的JSON。返回的是一段JS脚本(客户端的一个可执行的方法,参数为JSON 格式的数据,是要返回的数据)。如果单纯的返回JSON数据,虽然客户端也能看数据,但是却会报错,不能执行请求成功的回调函数。

    这里写图片描述

    报错原因,可以看下这里。其实就是我上面解释的,JSONP 的根本原理所要求的,要以这样的格式。

    这里写图片描述

  2. JSONP的局限性
    JSONP 方式,固然方便强大。但是他的局限性在于,它无法完成POST请求。即是我们将type改为post,在发送请求时,依然会是以Get的方式。

    这里写图片描述

    1. 注意JSON数据格式
      服务器端需要将字符串拼接转义,键名 需要使用双引号
  string str = "foo({\"staus\":\"world\"})";

CORS跨域

CORS原理

CORS(Cross-Origin-Resource Sharing,跨院资源共享)是一种允许多种资源(图片,Css文字,Javascript等)在一个Web页面请求域之外的另一个域的资源的机制。 跨域资源共享这种机制让Web应用服务器支持跨站访问控制,从而使得安全的进行跨站数据传输成为了可能。

具体方案

通过这种机制设置一系列的响应头,这些响应头允许浏览器与服务器进行交流,实现资源共享。

各语言设置响应头的方法

看一下具体Demo,同样是 最初的示例代码,这次我们不使用JSONP的跨域的方式,我们配置一下IIS 服务器(修改WebConfig文件),增添一下响应头。PS: 其他修改响应头方式,请见已上连接。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
 <system.webServer>
   <httpProtocol>
     <customHeaders>
       <add name="Access-Control-Allow-Origin" value="*" />
     </customHeaders>
   </httpProtocol>
 </system.webServer>
</configuration>

我们可以看一下运行结果:

这里写图片描述

* CORS 解决方案相对于JSONP 更加灵活,而且支持POST请求,是跨域的根源性解决方案。

引用补充:

刚刚说到的兼容性。CORS是W3C中一项较新的方案,所以部分浏览器还没有对其进行支持或者完美支持,详情可移至 http://www.w3.org/TR/cors/
安全问题。CORS提供了一种跨域请求方案,但没有为安全访问提供足够的保障机制,如果你需要信息的绝对安全,不要依赖CORS当中的权限制度,应当使用更多其它的措施来保障,比如OAuth2。

代理层

JSONP 和CORS 是主流的 跨域问题 的解决方案。除了他们呐,还有一种解决方案,就是代理层。简要说一下。

JS 调用本源的后台的方法(这样就不存在跨域的问题),而通过后台(任何具有网络访问功能的后台语言,ASP.NET ,JAVA,PHP等)去跨域请求资源,而后将结果返回至前台。

参考资料:
https://www.w3.org/TR/cors/
http://kb.cnblogs.com/page/139725/
http://www.freebuf.com/articles/web/65468.html
http://www.jb51.net/article/42629.htm
http://www.nowamagic.net/librarys/veda/detail/224/
http://www.open-open.com/lib/view/open1344558130468.html

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值