一、什么是ajax跨域问题
ajax跨域问题发生的根源,在于浏览器的同源策略。
什么是同源?
这里的“源”,又称为“域”,它是协议名、主机名、端口号的统称。而同源,则是指两个地址的“源”相同,也就是协议名、主机名、端口号完全相同
也就是说JavaScript只能访问和操作自己域下的资源,不能访问和操作其他域下的资源。
跨域问题是针对JS和ajax的,html本身没有跨域问题。
查看浏览器开发者工具Console报错:
Failed to load a.a.com:8080/A/FromServl…: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'b.b.com:8080' is therefore not allowed access.
http://baidu.com/http://www.baidu.com/×(域名不同)
http://www.baidu.com/https://www.baidu.com/×(协议不同)
http://localshot/http://127.0.0.1/×(域名不同)
http://localshot/http://localshot:8088/×(端口不同)
http://localshot/http://localshot/√
注意:localhost和127.0.0.1虽然都指向本机,但也属于跨域。
二、如何解决跨域
第一种方式:jsonp跨域
所谓jsonp就是在服务器端会给你输出一个字符串函数,你通过在本地定义一个同样名字的函数去执行就可以了。如果你不了解后端,也没有关系,你可以直接复制下面的例子来输出接口数据。
原生javascript跨域的例子:
<style type="text/css">
#con { width: 300px;height: 50px;}
#box div{ width: 300px; height: 30px; border: 1px solid red; }
</style>
<input type="text" id="con" value="" />
<div id="box"></div>
<script type="text/javascript">
var con=document.getElementById("con");
var box=document.getElementById("box");
var script1=null;
function callback(str){
var json=str.s;
for (var i=0; i<str.s.length;i++){
box.innerHTML+="<div>"+str.s[i]+"</div>"
}
}
con.onkeyup=function(){
box.innerHTML="";
if(script1){
document.body.removeChild(script1);
}
script1=document.createElement("script");
script1.src="[http://suggestion.baidu.com/su?cb=callback&wd="+con.value;](http://suggestion.baidu.com/su?cb=callback&wd=)
document.body.appendChild(script1);
};
</script>
jquery jsonp跨域的例子:
$.ajax({
async:false, // 是否是同步请求
url:"[http://ad.bjnews.com.cn/service/getad?pid=1](http://ad.bjnews.com.cn/service/getad?pid=1)",// 地址
type:"GET", // 请求方式
dataType:"jsonp", // 请求的数据类型
jsonp: 'callback', // callback的函数名
jsonpCallback:"callback_adservice",
data: {}, // 你要发送的数据 内容是名值对形式的
success:function(data){
alert(data)
},
//诊断错误类型
error:function(jqXHR,textStatus,errorThrown){
console.log(jqXHR);
console.log(textStatus);
console.log(errorThrown);
}
})
注意:jsonp 只支持get请求不支持post请求
第二种方式:跨域资源共享—CORS
跨源资源共享(CORS)是通过客户端+服务端协作声明的方式来确保请求安全的。服务端会在HTTP请求头中增加一系列HTTP请求参数(例如Access-Control-Allow-Origin等),来限制哪些域的请求和哪些请求类型可以接受,而客户端在发起请求时必须声明自己的源(Orgin),否则服务器将不予处理,如果客户端不作声明,请求甚至会被浏览器直接拦截都到不了服务端。服务端收到HTTP请求后会进行域的比较,只有同域的请求才会处理。
cors前端代码示例:
function getHello() {
var xhr = new XMLHttpRequest();
xhr.open("post", "[http://b.example.com/Test.ashx](http://b.example.com/Test.ashx)", true);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
// 声明请求源
xhr.setRequestHeader("Origin", "[http://a.example.com");](http://a.example.com/)
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
var responseText = xhr.responseText;
console.info(responseText);
}
}
xhr.send();
}
第三种方式:响应头添加Header允许访问
跨域资源共享(CORS)Cross-Origin Resource Sharing
这个跨域访问的解决方案的安全基础是基于"JavaScript无法控制该HTTP头"
它需要通过目标域返回的HTTP头来授权是否允许跨域访问。
response.addHeader(‘Access-Control-Allow-Origin:*’);//允许所有来源访问
response.addHeader(‘Access-Control-Allow-Method:POST,GET’);//允许访问的方式
第四种方式:Webpack使用代理proxy解决跨域问题
wepack默认http协议,如果要代理https协议,需要增加:
secure:false
proxyTable:
//当你请求是以v2开头的接口,则我帮你代理访问到https://api.douban.com
'/v2/*':{
target:'https:/api.douban.com', //你接口的域名
secure:false, //如果是https接口,需要配置这个参数
changeOrigin:true, //如果接口跨域,需要进行这个参数配置
}
}