1、首先编写后端代码,此时的域名:http://localhost:8088/text/1.php
<?php
function get ()
{
$data = [
'a' => 1,
'b' => 2
];
return $data;
}
echo json_encode(get());
2、编写前端代码,此时的域名:http://localhost:8808/text/demo/ajax.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<script src="https://cdn.bootcss.com/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<a href="#" οnclick="get()">发生ajax请求</a>
<script type="text/javascript">
function get ()
{
$.getJSON("http://localhost:8088/text/1.php").then(
function (result) {
console.log(result);
}
);
}
</script>
</body>
</html>
3、测试结果,报错
Failed to load http://localhost:8088/text/1.php: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost:8808' is therefore not allowed access.
4、产生跨域的原因
(1)浏览器限制:可以打开控制台发现,其实后台已经正确执行了,是浏览器不允许
(2)跨域:虽然域名相同,但端口不同
(3)XHR请求(XMLHttpRequest):只有XHR请求,浏览器才会限制
比如:<img src="http://localhost:8088/text/1.png">就不会出现错误
同时满足上面三个条件,才会发生跨域问题
5、解决思路:根据上面三个条件来解决
(1)解决浏览器限制:禁止浏览器检查,在命令行中
C:\Users\lenovo\AppData\Local\Google\Chrome\Application\chrome.exe --disable-web-security --user-data-dir
(2)不发出XHR请求:
使用jsonp来解决:
前端代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script type="text/javascript">
function callFunction (result) // 下面发出请求后,后端返回一个函数执行,js定义这个函数的行为
{
console.log(result);
}
</script>
<script type="text/javascript" src="http://localhost:8088/text/1.php?call=callFunction"></script> // 发出请求
</body>
</html>
后端代码:
<?php
header('Content-type: application/json');
$call = $_REQUEST['call'];
$data = [
'a' => 1,
'b' => 2
];
echo $call. '(' . json_encode($data) . ')'; // 返回一个带数据的函数,有js执行,为字符串
弊端:
1)服务器需要改动代码支持
2)只支持get
3)请求不是XHR
(3)解决跨域
1)被调用方解决:在服务器中添加header,允许来自...:8808的跨域访问,php文件的端口为:8088
<?php
header('Access-Control-Allow-Origin: http://localhost:8808'); // 所有都允许把域名改为*
function get ()
{
$data = [
'a' => 1,
'b' => 2
];
return $data;
}
echo json_encode(get());
补充:
// 响应类型
header('Access-Control-Allow-Methods: *');
// 响应头设置
header('Access-Control-Allow-Headers: x-requested-with, content-type');
// 当带有cookie的时候,origin必须是全匹配,不能使用*,且allow-credentials设置为true
header('Access-Control-Allow-Origin: http://localhost:8808');
header('Access-Control-Allow-Credentials', 'true');
当有cookie的时候,只能匹配一个域名,其他的怎么办呢??
这里可以先获取header中的origin的值,然后放到allow-origin中,
同样当有自定义头时,allow-headers也可以用这种方法
2)调用方解决
使用反向代理的方式
location /address {
proxy_pass localhost:8808
}