跨域问题主要是由于浏览器同源策略限制引起,简单来说,就是只相信自己人,不相信外人,只响应同域名发来的http请求,不相信其他域名发来的http请求。好处是减少上当受骗的几率,缺点是不符合webapi的大趋势,api访问会受限。
浏览器同源策略
同源策略(Same origin policy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说 Web 是构建在同源策略基础之上的,浏览器只是针对同源策略的一种实现。
它的核心就在于它认为自任何站点装载的信赖内容是不安全的。浏览器只被允许访问来自同一站点的资源
,而不是那些来自其它站点可能怀有恶意的资源。
同源是指:域名、协议、端口
相同。
跨域资源共享(CORS) 是一种机制,它使用额外的 HTTP 头来告诉浏览器 让运行在一个 origin (domain) 上的Web应用被准许访问来自不同源服务器上的指定的资源。当一个资源从与该资源本身所在的服务器不同的域、协议或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。
CORS(跨域资源共享)
CORS(Cross-origin resource sharing,跨域资源共享)是一个 W3C 标准,定义了在必须访问跨域资源时,浏览器与服务器应该如何沟通。CORS 背后的基本思想,就是使用自定义的 HTTP 头部(origin、method)让浏览器与服务器进行沟通,从而决定请求或响应是应该成功,还是应该失败。
CORS 需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE 浏览器不能低于 IE10。
整个 CORS 通信过程,都是浏览器自动完成,不需要用户参与
。对于开发者来说,CORS 通信与同源的 AJAX 通信没有差别,代码完全一样。浏览器一旦发现 AJAX 请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求(非简单请求),但用户不会有感觉。
因此,实现 CORS 通信的关键是服务器。只要服务器实现了 CORS 接口,就可以跨源通信。
浏览器将CORS请求分成两类:简单请求
(simple request)和非简单请求
(not-so-simple request)。
只要同时满足以下两大条件,就属于简单请求。
1、请求方法是以下三种方法之一:HEAD
、GET
、POST
2、HTTP的头信息不超出以下几种字段:Accept
、Accept-Language
、Content-Language
、Last-Event-ID
、Content-Type
Content-Type:只限于三个值application/x-www-form-urlencoded
、multipart/form-data
、text/plain
凡是不同时满足上面两个条件,就属于非简单请求。
浏览器对这两种请求的处理,是不一样的。
简单请求
在请求中需要附加一个额外的 Origin
头部,其中包含请求页面的源信息(协议、域名和端口),以便服务器根据这个头部信息来决定是否给予响应。例如:Origin: http://www.abc.com
如果服务器认为这个请求可以接受,就在Access-Control-Allow-Origin
头部中回发相同的源信息(如果是公共资源,可以回发 * )。例如:Access-Control-Allow-Origin:http://www.abc.com
没有这个头部或者有这个头部但源信息不匹配,浏览器就会驳回请求。正常情况下,浏览器会处理请求。注意,请求和响应都不包含 cookie 信息。
如果需要包含 cookie 信息,ajax 请求需要设置 xhr 的属性 withCredentials
为true
,服务器需要设置响应头部Access-Control-Allow-Credentials: true
。
服务器需要做的工作:
1.设置允许访问本接口的网址
2.设置允许访问本接口的请求类型
3.设置允许访问本接口的头
非简单请求
浏览器在发送真正的请求之前,会先发送一个 Preflight 请求给服务器,这种请求使用 OPTIONS
方法,发送下列头部:
Origin
:与简单的请求相同。
Access-Control-Request-Method
: 请求自身使用的方法。
Access-Control-Request-Headers
: (可选)自定义的头部信息,多个头部以逗号分隔。
例如:
1、浏览器先发送一个Option
请求到服务器
Origin: http://www.abc.com
Access-Control-Request-Method: POST
Access-Control-Request-Headers: token
2、发送这个请求后,服务器可以决定是否允许这种类型的请求。服务器通过在响应中发送如下头部与浏览器进行沟通:
Access-Control-Allow-Origin:与简单的请求相同。
Access-Control-Allow-Methods: 允许的方法,多个方法以逗号分隔。
Access-Control-Allow-Headers: 允许的头部,多个方法以逗号分隔。
Access-Control-Max-Age: 应该将这个 Preflight 请求缓存多长时间(以秒表示)。
例如:
Access-Control-Allow-Origin: http://www.abc.com
Access-Control-Allow-Methods: GET, POST
Access-Control-Allow-Headers: token
Access-Control-Max-Age: 1728000
一旦服务器通过 Preflight 请求允许该请求之后,以后每次浏览器正常的 CORS 请求,就都跟简单请求一样了。
预请求只在第一次发生,检测通过后,后面请求时不会再发出
Option
请求
服务器需要做的工作:
1.设置允许访问本接口的网址
2.设置允许访问本接口的请求类型
3.设置允许访问本接口的头
优点
CORS 通信与同源的 AJAX 通信没有差别,代码完全一样,容易维护。
支持所有类型的 HTTP 请求。
缺点
存在兼容性问题,特别是 IE10 以下的浏览器。
第一次发送非简单请求时会多一次请求。
案例一:
这就是个简单请求
$ajax({
url:"http://www.abc.com/api.php?action=getlogo",
data:{siteid:123}
})
案例二:
这是一个非简单请求,因为headers中加入了自定义头参考:
https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS
https://www.cnblogs.com/laixiangran/p/9064769.html