为什么会发生AJAX跨域问题?
浏览器限制(浏览器不允许跨域)
请求跨域(发出去的请求[其中协议,域名,端口任何一个不一样,浏览器就认为是跨域的]不是本域的)
发送的是XHR类型请求(如果不是xhr类型的请求,就算跨域,浏览器也不会报错)
这三个条件同时满足, 才有可能产生跨域安全问题.
所以跨域问题是浏览器校验请求时发生的,和服务器端没有关系.
解决思路
允许浏览器跨域(不推荐 因为这是客户端手工操作)
XHR换成JSONP(有弊端,下面会讲)
跨域(让被调用方修改支持跨域 或者 调用方修改支持跨域)
全面解决跨域问题过程
允许浏览器跨域(以Chrome为例) 不推荐
在Chrome的安装目录下 找到chrome.exe,用命令行加参数启动(按住shift不松,右键选择在此处打开命令窗口)
jsonp解决跨域问题(有弊端)
本次url返回结果为{"data":"get1 ok"}
ajax发送请求的时候,预期服务器返回的数据类型dataType填为 jsonp ,这时候发送类型是script , 返回的是一段JS脚本
服务器将结果数据返回 , 将返回的数据变成JS函数的参数,函数名是前端传参callback的值
服务器必须增加如下的JAVA类,指定识别传来的calback参数
不懂ControllerAdvice注解的看这里(https://www.cnblogs.com/magicalSam/p/7198420.html)
JSONP的弊端
服务器需要改动代码支持
只支持GET方法
发送的不是XHR(XHR有很多好的特性)请求
跨域
被调用方解决
服务器端实现
被调用方添加一个过滤器,每次请求的时候带上允许跨域的字段.
如果允许所有的地址调用 将access-Controller-allow-origin设置为*,方法同理.
简单请求会先执行服务器代码然后浏览器再判断是否可以跨域 而非简单请求浏览器会先发送一个预检请求(方法类型为OPTIONS)判断是否可以跨域,再执行服务器代码.
下面是常见的简单请求和非简单请求
如果碰到下面这种情况,可能是非简单请求造成的
根据报错,在过滤器中允许跨域 res.addHeader("access-Controller-allow-headers","content-type")
缓存预检命令,提高效率,此处缓存1个小时 res.addHeader("access-Controller-max-age","3600")
带Cookie的跨域(例如8081端口想获取8080端口的cookie, 是调用方获取被调用方的cookie)
带cookie的跨域,access-Controller-allow-Origin必须全匹配,不能用*,而且还要设置access-Controller-allow-Credentials为true
但这样做又有新的问题...那就是被调用方只支持一个调用方调用,因为不能使用*号了.
解决方案
带自定义头的跨域
NGINX解决方案
hosts文件中配置好虚拟主机后,在nginx的配置文件中配置如下节点.
Spring框架解决
如果用的是Spring框架,Controller上直接添加注解@CrossOrigin支持跨域. Spring大法好.
NGINX调用方隐藏跨域
相同域名的不同URL转向不同的应用服务器.因为是相同域名,所以不会跨域.