阅读 114

ajax跨域问题

 

什么是跨域问题?
跨域问题来源于JavaScript的"同源策略",即只有 协议+主机名+端口号 (如存在)相同,则允许相互访问。也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。跨域问题是针对JS和ajax的,html本身没有跨域问题。

查看浏览器开发者工具Console报错:

Failed to load http://a.a.com:8080/A/FromServlet?userName=123: No ‘Access-Control-Allow-Origin‘ header is present on the requested resource. Origin ‘http://b.b.com:8080‘ is therefore not allowed access.

http://www.abc.com/a/b 调用 http://www.abc.com/d/c(非跨域)

http://www.abc.com/a/b 调用 http://www.def.com/a/b (跨域:域名不一致)

http://www.abc.com:8080/a/b 调用 http://www.abc.com:8081/d/c (跨域:端口不一致)

http://www.abc.com/a/b 调用 https://www.abc.com/d/c (跨域:协议不同)

请注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。

 

 

跨域问题怎么解决?
1、响应头添加Header允许访问

2、jsonp 只支持get请求不支持post请求

3、httpClient内部转发

4、使用接口网关——nginx、springcloud zuul   (互联网公司常规解决方案)

 

解决方式1:响应头添加Header允许访问
跨域资源共享(CORS)Cross-Origin Resource Sharing

response.addHeader(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
response.addHeader(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式
 

解决方式2:jsonp 只支持get请求不支持post请求
用法:①dataType改为jsonp     ②jsonp : "jsonpCallback"————发送到后端实际为http://a.a.com/a/FromServlet?userName=644064&jsonpCallback=jQueryxxx     ③后端获取get请求中的jsonpCallback    ④构造回调结构

$.ajax({
type : "GET",
async : false,
url : "http://a.a.com/a/FromServlet?userName=644064",
dataType : "jsonp",//数据类型为jsonp
jsonp : "jsonpCallback",//服务端用于接收callback调用的function名的参数
success : function(data) {
alert(data["userName"]);
},
error : function() {
alert(‘fail‘);
}
});
 

//后端
String jsonpCallback = request.getParameter("jsonpCallback");
//构造回调函数格式jsonpCallback(数据)
resp.getWriter().println(jsonpCallback+"("+jsonObject.toJSONString()+")");
JSONP实现原理
在同源策略下,在某个服务器下的页面是无法获取到该服务器以外的数据的,即一般的ajax是不能进行跨域请求的。但 img、iframe 、script等标签是个例外,这些标签可以通过src属性请求到其他服务器上的数据。利用

然后后端就会执行jsonpCallback(传递参数 ),把数据通过实参的形式发送出去。

  使用JSONP 模式来请求数据的整个流程:客户端发送一个请求,规定一个可执行的函数名(这里就是 jQuery做了封装的处理,自动帮你生成回调函数并把数据取出来供success属性方法来调用,而不是传递的一个回调句柄),服务器端接受了这个 jsonpCallback函数名,然后把数据通过实参的形式发送出去

 

(在jquery 源码中, jsonp的实现方式是动态添加