跨域问题
跨域
同源策略
同源:域名、协议、端口号相同的地址。不同源地址之间默认不能进行请求。
通过img尝试跨域请求
可以发送不同源地址之间的请求,但不能得到响应体。因为浏览器会将地址中的图片转化成二进制,无法通过字符串响应回来
通过link尝试跨域请求
可以发送不同源地址之间的请求,但不能得到响应体。因为 不能拿到link中链入文件的内容
通过script尝试跨域请求
可以发送不同源地址之间的请求,但不能得到响应体。因为不能拿到script中引入文件的内容,但是可以通过在引入文件中设置js编码格式,并通过调用主页面上的方法来自动输出服务器内容
解决方法
jsonp
-
通过script标签完成不同源地址之间的跨域请求
-
通过script标记请求一个服务端的PHP文件,而这个文件返回的是js代码,而js作用是调用事先定义好的函数,从而将服务端想要给客户端发过去的数据发送给客户端
<script src='../jquery.js'></script>
<script>
//因为多次调用同一个函数会覆盖,所以随机生成函数名 //按照函数命名法则,第一位不是数字,中间不能有.
var callback_name='ashen_'+Date.now()+Math.random().toString().substr(2,5);
var script=document.createElement('script');
//设置get的特定url
script.src='http://localhost:88/day12/code/jsonp/jsonp.php?'+'callback_name='+callback_name;
document.body.appendChild(script);
//函数输出服务端结果 因为当请求还未完成时,无法得到res,所以定义为页面加载函数,页面执行完成才执行
window[callback_name]=function(res){
console.log(res);
}
</script>
<?php
//将编码方式设置为application/javascript,才能调用客户端方法输出数据
$timenow = time();
//如果客户端没有给出特定url即特定调用的函数,则直接输出json数据
if (empty($_GET['callback_name'])) {
header('Content-Type:application/json');
echo json_encode($timenow);
exit();
}
header('Content-Type:application/javascript');
//否则将json数据反序列化赋值给result
$result = json_encode($timenow);
//获取传入的函数名,赋值给$callback_name
$callback_name = $_GET['callback_name'];
//如果$callback_name类型是函数,则输出结果
echo "typeof {$callback_name}==='function' && {$callback_name}({$result})";
17.5.1 封装jsonp,服务端代码如上
function jsonp(url,params,callback){
//获取随机函数名
var callback_name='jsonp_'+Date.now()+Math.random().toString().substr(2,5);
//判断params即传入数据类型 当为对象时......
if (typeof params === 'object') {
var tempArr = [];
for (var key in params) {
var value = params[key];
tempArr.push(key + '=' + value);
}
params = tempArr.join('&');
}
//创建script
var script=document.createElement('script');
//设置src 将url 传入的数据 函数名传入 callback是get方法传输的一个键
script.src=url+'?'+params+'&callback='+callback_name;
document.body.appendChild(script);
//向页面加载函数中添加名为callback_name的函数,并在其中调用此函数
window[callback_name] = function (data) {
callback(data)
//执行完后,删除页面加载中的此函数 删除页面中的此script
delete window[callback_name]
document.body.removeChild(script)
}
}
jsonp('http://localhost:88/day12/code/jsonp/jsonp.php',{id:123},function(res){
console.log(res);
})
17.6 跨域资源共享(cors)
设置被访问页面的Access-Control-Allow-Origin为* 允许任何页面访问,Access-Control-Allow-Origin为特定url,允许该页面访问
proxy请求转发代理
在vue或react项目中,可以直接通过原本提供的proxy转发跨域请求。通过设置proxy,可以实现转跨域请求为同域请求