Ajax跨域请求

domain

1
https://mail.google.com/mail/#inbox

以上URL的构成:

1
2
3
4
5
6
http:					协议名,也就是HTTP超文本传输协议
mail 服务器名
google.com 域名
mail.google.com 网站名
/ 根目录
`#inbox` 根目录下的默认网页

1. 什么是跨域请求?

请求的资源所在的协议/域名/端口号三者之一与当前资源不一致即为跨域请求。

关于Ajax环境的搭建先略过,直接来一段demo看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<h2>非跨域请求</h2>
<button id="btn1">非跨域按钮</button>
<h2>跨域请求</h2>
<button id="btn2">跨域按钮</button>
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.js"></script>
<script>
$('#btn1').click(function(obj){
$.get('http://localhost:8081/Ajax/2.php',function(){
console.log('btn1被单击后发起的XHR请求');
console.log(obj);
})
})

$('#btn2').click(function(obj){
$.get('https://unsplash.com',function(){
console.log('btn2被单击后发起的XHR请求');
console.log(obj);
})
})
</script>
</body>
</html>

PHP代码:

1
2
3
4
<?php
header('Content-Type: application/json; charset=utf8');
$data = ['uname'=>'Tom','age'=>20];
echo json_encode($data);

在浏览器地址栏输入http://localhost:8081/Ajax/cross.html打开页面。
点击’非跨域按钮’,查看控制台发现,请求是成功的,并且可以看见事件对象。

点击’跨域按钮’,查看控制台,发现XHR请求失败了,因为请求的域名不同。

2. 浏览器允许跨域请求吗?

允许:< img src="跨域的图片">
允许:<link rel="stylesheet" href="跨域的CSS">
允许:<a href="跨域的链接">
允许:<script src="跨域的JS">
禁止:AJAX请求不允许跨域

处于安全原因的考虑,所有的浏览器默认禁止使用XHR异步的跨域请求。

比如img图片跨域:

1
< img src="https://images.unsplash.com/photo-1425342605259-25d80e320565?dpr=2&auto=format&fit=crop&w=1080&h=720&q=80&cs=tinysrgb&crop=">

不同协议名、不同域名,网页正常显示图片,说明允许跨域。

图像跨域主要有两个缺点:1.只能发送get请求。2.无法访问服务器的响应文本所以,图像跨域只能用于浏览器与服务器间的单项通信。

##3. 跨域解决方案

1. 设置”Access-Control-Allow-Origin”头部

在PHP页面中设置Access-Control-Allow-Origin头部信息

PHP代码:

1
2
3
4
5
6
7
<?php
header('Content-Type: application/json; charset=utf8');

// 指定允许其他域名访问
header('Access-Control-Allow-Origin:*');
$data = ['uname'=>'Tom','age'=>20];
echo json_encode($data);

在浏览器http://localhost:8081/Ajax/cross.html页面中发现,跨域请求是成功的。

2. 使用JSONP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<button id="crossBtn">跨域按钮</button>

<script>
function doResponse(obj){
alert(obj.uname+obj.age);
}

$('#crossBtn').click(function(){
$.ajax({
url:'http://127.0.0.1:8081/Ajax/3.php',
success:doResponse
})
})
</script>

PHP代码:

1
2
3
4
5
6
7
8
<?php
header('Content-Type: application/json');

$data = ['uname'=>'Tom','age'=>20];

$json = json_encode($data); //返回一个json{"":"","":20}'

echo 'doResponse('.$json.')';

在$.ajax 方法中有一个 dataType属性,如果将该属性设置成 dataType:”jsonp”,就能实现跨域
将$请求稍作修改:

1
2
3
4
5
6
7
$('#crossBtn').click(function(){
$.ajax({
url:'http://127.0.0.1:8081/Ajax/3.php',
dataType:'jsonp',
success:doResponse
})
})

再次打开页面查看,就可以获取到PHP文件中数据了。