知识小结:
1.跨域的问题不是服务器的问题,是浏览器不允许跨域 从而报错。
2.协议 ip 端口,只要其中一个前后端不同,浏览器都视为跨域。
3.只有X-Requested-With为XMLHttpRequest的情况下才会发生跨域的问题。 而$.get $.post $.ajax都是XMLHttpRequest的类型,所以产生跨域问题。getJsonP就是通过绕过这个类型来解决跨域的问题的。
4.Cookie跨域:不能由前端跨域设置,例如如果页面时127.0.0.1,无法再127.0.0.1的页面向localhost植入Cookie。只能在localhost本域注入Cookie,127.0.0.1可以跨域传输localhost的Cookie给后端(后端也是localhost域)。因此跨域Cookie的植入一般由后端完成。
解决方案
5.为了安全,建议由后端植入Cookie,并且设置为HttpOnly。以防止脚本操纵核心Cookie
6.非简单请求,会发送OPTIONS预检命令,看是否支持某些字段的修改,例如自定义Header,自定义Content-Type等。发送预检命令的时间由Access-Control-Max-Age来定,单位为秒。
跨域具体方案:
1. 让后台修改,支持某些前端域名的跨域。php代码如下:
header('Access-Control-Allow-Origin:*'); //支持所有前端域名,但是*有个问题,就是不支持Cookie的跨域
也可以动态设置跨域。header('Access-Control-Allow-Origin:'.$_SERVER['HTTP_ORIGIN']);//如果请求涉及到跨域,那么origin会自动带上前端域名信息。这样做还有一个好处,可以支持cookie跨域
2. jsonp。 讲get请求伪装成一个script文件的加载。就可以绕过跨域的问题为了。
缺点:需要后台做修改;只能用get方法;发出去的不是xhr请求;
jquery的jsonp底层实现原理如下:
<body>
<script>
function showData (result) {
alert(result.message);
}
$(document).ready(function () {
$("#btn").click(function () {
$("head").append("<script src='http://localhost/frontpage/test.php?callback=showData'><\/script>");
});
});
</script>
<input type='text' id='text' />
<button id="btn">btn</button>
</body>
</html>
<?php
header('Content-Type:application/json; charset=utf-8');
$output = array(
"status"=>-100,
"message"=>"返回资讯",
"data"=>NULL
);
echo 'showData'.'('.json_encode($output).')'; //post request
exit(0);
jsonp的使用如下:
<script>
//function showData (result) {
// alert(result.message+"ddg");
//}
$(document).ready(function () {
$("#btn").click(function () {
$.ajax({
url: "http://localhost/frontpage/test.php",
type: "GET",
dataType: "jsonp", //指定服务器返回的数据类型
//jsonpCallback: "showData", //指定回调函数名称
success: function (result) {
alert(result.message);
}
});
});
});
</script>
<input type='text' id='text' />
<button id="btn">btn</button>
</body>
</html>
<?php
header('Content-Type:application/json; charset=utf-8');
$output = array(
"status"=>-100,
"message"=>"返回资讯",
"data"=>NULL
);
echo $_GET['callback'].'('.json_encode($output).')'; //post request
exit(0);
3. 自定义header进行跨域
自定义的Header跨域可以通过:前端设置Header、后端设置Access-Control-Allow-Headers来解决。
Cookie跨域,只能通过后端设置(前端配合);不能通过前端直接设置跨域的Cookie。
简单请求不会触发OPTIONS命令,非简单请求会触发OPTIONS,可以通过MAX-AGE设置触发OPTIONS的间隔。
简单请求和非简单请求可以参看百度。
$.ajax({
url: 'http://localhost/frontpage/test.php',
type: 'POST',//or GET DELETE PUT
cache:false,//务必false,某些浏览器如果不是false,会有缓存。只有HEADER和GET可能有缓存,所以只有他们2个需要手动设置cache为false。其他指令都是默认false,因此强烈建议所有请求都用POST
//注意新增请求头,会首先调用OPTIONS方法,来看后端是否支持。
headers:{//添加头方法1
"h1":"yes1",
"h2":"yes2",
//"cookie":"my1=3bc"
},
beforeSend:function(xhr){//添加头方法二,可以设置header,cookie
xhr.setRequestHeader("h3",34444);
xhr.setRequestHeader("h4",34444);
//xhr.setRequestHeader("af2","34444");
//$.cookie('yy', 4446664444, { expires: 7,path: '/',domain:'other_domain' });//前端跨域设置,无效果。只能在other_domain本域设置。
},
xhrFields:{//
withCredentials:true//允许前端把跨域的Cookie带给后端[允许后端向前端植入cookie]。是被调用方域名的cookie
},
data: {'title':'test334'},
success: function(response){
console.log(response.status)
$.cookie("token",response.data,{expires:7,path:'/'});
location.href='index.html';
},
complete: function(XMLHttpRequest, textStatus,a,b,c,ed,f){
console.log(textStatus);
},
error: function(XMLHttpRequest, textStatus, errorThrown){
console.log("dg");
//通常情况下textStatus和errorThrown只有其中一个包含信息
//this; //调用本次ajax请求时传递的options参数
}
});
<?php
header('Content-Type:application/json; charset=utf-8');//设置返回格式
//header('Access-Control-Allow-Headers:h1,h2,h3,h4');//支持自定义的header
header('Access-Control-Allow-Origin:'.$_SERVER['HTTP_ORIGIN']);//动态支持跨域
header("Access-Control-Allow-Credentials:true");///支持cookie额跨域,允许后端跨域设置Cookie。
//setCookie("name","value");
if($_SERVER["REQUEST_METHOD"]=="OPTIONS"){
header("Access-Control-Max-Age: 5");//设置预检请求的有效期,单位是秒【OPTION】。
header('Access-Control-Allow-Headers:'.$_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']);//支持自定义的header
exit(0);
}
$output = array(
"status"=>-100,
"message"=>"返回资讯",
"data"=>$_SERVER
);
//echo $_GET['callback'].'('.json_encode($output).')'; //post request
echo json_encode($output); //post request
exit(0);
翻译
搜索
复制