跨域 && 解决方法

为什么会出现跨域问题 —— 同源策略

跨域限制仅仅是浏览器的行为,服务器没有跨域限制。

同时满足以下三个条件才有可能发生跨域问题:

  1. 浏览器限制

  2. 跨域

  3. XMLHttpRequest 请求

跨域的概念:协议、域名、端口都相同才叫同域,否则都叫跨域

出于安全考虑,服务器不允许ajax跨域获取数据,但是可以跨域获取文件内容。

  • 举个简单的例子:在编写网页的时候,<img src = ‘www.xxxx.xxxx/’ > URL 不是本域的也可以获取数据

  • 当我们发送 XMLHttpRequest 请求的时候,如果请求的是别的域,那么就会产生跨域问题,客户端无法获取服务器端返回的数据

  • 跨域的问题是发生在 XMLHttpRequest 请求的,也就是说,如果不是 XMLHttpRequest 请求,是不会产生跨域问题的。

解决跨域的方法

从浏览器出发

使用相关的参数启动浏览器,解决跨域

通用性极低,不推荐

JSONP 解决跨域

什么是 JSONP ?

script 标签中的 src 属性是可以跨域的。jsonp 是浏览器端发送请求之后,服务器端包装好一段 json 数据,并放在一个 callback 函数中,返回一个 js 文件。浏览器端动态引入这个 js 文件,就会调用这个 callback 函数,获取到数据。

原理:

首先在客户端注册一个 callback ,然后把 callback 的名字传给服务器。此时,服务器先生成 json 数据,然后以 javascript 语法的方式,生成 function,function 名字就是传递上来的 callback 名称。最后将 json 数据直接以入参的方式,放置 function 中,这样就生成 js 语法的文档,返回给客户端。客户端浏览器,解析 script变迁,并执行返回 javascript 文档,此时数据作为参数,传入了客户端预先定义好的 callback 函数里。

例子:

跨域服务端提供的js脚本动态生成,这样调用者可以传一个参数过去告诉跨域服务端“我想要一段调用XXX函数的js代码,请你返回给我”,于是跨域服务器就可以按照客户端的需求来生成js脚本并响应了。


//跨域服务器

//文件:flightResult.php

flightHandler({
    "code":"CA1998",
    "price": 1780,
    "tickets": 5
});

//本地

<script type="text/javascript"> 
    // 得到航班信息查询结果后的回调函数 
    var flightHandler = function(data){
        alert('你查询的航班结果是:票价 ' + data.price + ' 元,' + '余票 ' + data.tickets + ' 张。');
    }; 
    // 提供jsonp服务的url地址(不管是什么类型的地址,最终生成的返回值都是一段javascript代码) 
    var url = "跨域服务器/flightResult.php?code=CA1998&callback=flightHandler";
    // 创建script标签,设置其属性 
    var script = document.createElement('script'); 
    script.setAttribute('src', url); 
    // 把script标签加入head,此时调用开始 
    document.getElementsByTagName('head')[0].appendChild(script); 
</script>

缺点:

  1. 只支持 GET 请求而不支持 POST 等其它类型的 HTTP 请求 – 因为 script 标签,只支持GET

  2. 只支持跨域 HTTP 请求这种情况,不能解决不同域的两个页面之间如何进行 JavaScript 调用的问题。

CORS 解决跨域问题

一、CORS 简介:

CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

二、两种请求

浏览器将 CORS 请求分为两类:简单请求和非简单请求

只要同时满足一下两个条件,就属于简单请求,反之为非简单请求

  1. 请求方法是以下三种方法之一:
  • HEAD
  • GET
  • POST
  1. HTTP的头信息不超出以下几种字段:
  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain

三、简单请求

对于简单请求,浏览器直接发出 CORS 请求 :在头部信息中,直接加入一个 Origin 字段

GET /cors HTTP/1.1
Origin: http://api.bob.com
Host: api.alice.com
Accept-Language: en-US
Connection: keep-alive
User-Agent: Mozilla/5.0...

Origin 字段用来说明本次请求来自哪个源(协议+域名+端口)。服务器根据这个值,决定是否同意这次请求。

  1. 如果 Origin 指定的源不在许可范围内,服务器会返回一个正常的 http 回应。这个回应的头信息没有包含 Access-Control-Allow-Origin 字段,浏览器就会知道出错了,从而抛出一个错误,被 XMLHttpRequest 的 onerror 回调函数捕获。

注意,这种错误无法通过状态码识别,因为返回的状态码可能是 200 。

  1. 在许可范围之内,服务器返回的响应,会多出几个头信息的字段
Access-Control-Allow-Origin: http://api.bob.com  //请求时 Origin 字段的值或者 * ,表示接受对应域名的请求
Access-Control-Allow-Credentials: true  //表示是否允许发送 cookie
Access-Control-Expose-Headers: FooBar //拿到指定字段
Content-Type: text/html; charset=utf-8

猜你喜欢

转载自blog.csdn.net/weixin_42186513/article/details/83417923