什么是跨域
跨域,指的是浏览器不能让XmlHttpRequest对象(ajax)执行其他网站的脚本。
它是由浏览器的同源策略造成的,是浏览器对JavaScript施加的安全限制。
所谓同源是指,域名,协议,端口均相同,举个栗子:
http://www.123.com/index.html 调用 http://www.123.com/server.PHP (非跨域)
http://www.123.com/index.html 调用 http://www.456.com/server.php 主域名不同:123/456,跨域)
http://abc.123.com/index.html 调用 http://def.123.com/server.php (子域名不同:abc/def,跨域)
http://www.123.com:8080/index.html 调用 http://www.123.com:8081/server.php (端口不同:8080/8081,跨域)
http://www.123.com/index.html 调用 https://www.123.com/server.php (协议不同:http/https,跨域)
请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。
浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。
如何解决跨域
方法1:JSONP
虽然浏览器的同源策略不能让XmlHttpRequest对象之间访问其他域的资源,但是当需要通讯时,本站脚本创建一个并提供一个回调函数来接收数据(函数名可约定,或通过地址参数传递)。
第三方API产生的响应为json数据的包装(故称之为jsonp,即json padding),形如:
callback({"name":"hax","gender":"Male"}) 这样浏览器能通过。
此种方式最大的优点就是几乎所有浏览器都支持,兼容性好,但它只能处理GET请求。为什么?
因为没有这种搞法呀!
。
<script src="http://xxx.com/api" method="post"/> 。
方法2:CORS
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。
它允许浏览器向跨源服务器,发出XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。
CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。
浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。
因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。
CORS具体流程:
对于简单请求,浏览器直接发出CORS请求。具体来说,就是在头信息之中,增加一个Origin字段。
下面是一个例子,浏览器发现这次跨源AJAX请求是简单请求,就自动在头信息之中,添加一个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字段用来说明,本次请求来自哪个源(协议 + 域名 + 端口)。
服务器根据Origin指定的域名判断是否要接受这个请求。
如果Origin指定的源,不在许可范围内,服务器会返回一个正常的HTTP回应。浏览器发现,这个回应的头信息没有包含Access-Control-Allow-Origin字段,就知道出错了,从而抛出一个错误,被XMLHttpRequest的onerror回调函数捕获。
注意,这种错误无法通过状态码识别,因为HTTP回应的状态码有可能是200。
服务器如果接受此origin,在处理请求后返回的响应中要添加CORS标准中指定的请求头,多出几个头信息字段。
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
上面的头信息之中,有三个与CORS请求相关的字段,都以Access-Control-开头。
(1)Access-Control-Allow-Origin
该字段是必须的。它的值要么是请求时Origin字段的值,要么是一个*,表示接受任意域名的请求。
(2)Access-Control-Allow-Credentials
该字段可选。它的值是一个布尔值,表示是否允许发送Cookie。默认情况下,Cookie不包括在CORS请求之中。设为true,即表示服务器明确许可,Cookie可以包含在请求中,一起发给服务器。这个值也只能设为true,如果服务器不要浏览器发送Cookie,删除该字段即可。
(3)Access-Control-Expose-Headers
该字段可选。CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:
Cache-Control
Content-Language
Content-Type
Expires
Last-Modified
Pragma
如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。
上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值。
springboot实现跨域cors
增加一个配置类
上面几行代码简单的在服务器端解决了跨域问题。
参考文章:https://www.jianshu.com/p/868a9e53c6bc,https://mp.weixin.qq.com/s/9Jr_nRNY0jCG8-4zh1YXAQ
代码地址: https://gitee.com/blueses/spring-boot-demo