【跨域请求(七)】CORS 跨资源共享《单向跨域》

传送门:
1. JavaScript 教程 / 浏览器模型 / CORS 通信
2. CORS ajax跨域请求php简单完整案例一则
3. Content-Type 详解
4. OPTIONS预检请求

一、简单请求

在这里插入图片描述

  • a.html(http://aaa.com/a.html)
<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title></title>
</head>
<body>
	<input type="button" id="btn" value="点击获取随机图片" onclick="getRandomPic()" />
	<div class="demo"></div>
	<script>
		function getRandomPic() {
			// ajax 向同域后端文件发出请求,接收数据
			var xhr = new XMLHttpRequest();
			xhr.open('GET', 'http://bbb.com/b.php?random=' + Math.random(), true);
			xhr.onreadystatechange = function() {
				if (this.readyState === 4) {
					if ((this.status >= 200 && this.status < 300)
					|| (this.status === 304)) {
						var imgURL = this.responseText;
						document.querySelector('.demo').innerHTML =
						'<img src="' + imgURL + '" width=500 />';
					} else {
						console.log(new Error);
					}
				}
			};
			// 向服务器发出请求是否携带 Cookie(某些浏览器默认 false,某些则为 true)
			xhr.withCredentials = true;
				// 需要配合服务器设置 'Access-Control-Allow-Credentials: true' 字段
			xhr.send(null);
		}
	</script>
</body>
</html>
  • b.php(http://bbb.com/b.php)
<?php
	// 指定允许访问的域名(必需)
	header('Access-Control-Allow-Origin: http://aaa.com');
	
	// 指定允许响应的类型(可选,除去这三种之外的,都是非简单请求)
	header('Access-Control-Allow-Methods: POST, GET, HEAD');
	
	// 指定是否允许携带 Cookie 发送请求(可选,默认 false)
	header('Access-Control-Allow-Credentials: true');
		# 需要配合客服端的 XMLHttpRequest.withCredentials = true; 属性
	
	// 告知服务端以 HTML文档标记 格式处理请求数据
	header('Content-type: text/html; charset=utf-8');
	
	// 发送过来的随机数
	$random = $_GET['random'];

	// 输出一个带有随机参数的图片地址,防止地址被缓存而固定为一张图片
	echo 'https://uploadbeta.com/api/pictures/random/?key=BingEverydayWallpaperPicture&random='.$random;
?>

二、非简单请求

1. OPTIONS 预检请求

模拟:ajax向服务器发送的请求中,携带 Content-Type 字段的类型为 application/json
【b.php 可空白,不进行任何处理,此处只是模拟预检请求
在这里插入图片描述
这是由于 a.html 的 ajax 中设置了 xhr.setRequestHeader(‘Content-Type’, ‘application/json’); 浏览器将该请求识别为了非简单请求。

<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title></title>
</head>
<body>
	<script>
		var xhr = new XMLHttpRequest();
		xhr.open('POST', 'http://bbb.com/b.php', true);
		xhr.setRequestHeader('Content-Type', 'application/json');
		xhr.send(null);
	</script>
</body>
</html>

2. 示例

  • a.html(http://aaa.com/a.html)
<!DOCTYPE html>
<html lang="zh">
<head>
	<meta charset="UTF-8">
	<meta name="viewport" content="width=device-width, initial-scale=1.0">
	<meta http-equiv="X-UA-Compatible" content="ie=edge">
	<title></title>
</head>
<body>
	<script>
		// 转为JSON字符串(POST、GET请求会强制转换为字符串类型,这里需要处理下)
		var obj = JSON.stringify({
			name: '张三',
			age: 14,
			domain: 'http://aaa.com'
		});
		
		var xhr = new XMLHttpRequest();
		xhr.open('POST', 'http://bbb.com/bb.php', true);
		xhr.onreadystatechange = function() {
			if (this.readyState === 4) {
				if ((this.status >= 200 && this.status < 300)
				|| (this.status === 304)) {
					console.log(this.responseText);
				} else {
					console.log(new Error);
				}
			}
		};
		// 这是POST请求通常设置的字段信息(必需)
		xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			// 注意,因为还需要再设置多一个字段,所以结尾不应该有分号
		
		// 向服务器发送json数据时需要设置的字段
		xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
			// 虽然也可以直接使用上面字段,但是设置本字段会触发"预检"OPTIONS请求
		
		// 或者写在一起,逗号隔开
		// xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded, application/json; charset=utf-8');
		
		xhr.send('data=' + obj);
	</script>
</body>
</html>
  • b.php(http://bbb.com/b.php)
<?php
	// 指定允许访问的域名(必需)
	header('Access-Control-Allow-Origin: http://aaa.com');
	
	// 指定允许响应的类型(必需)
		# 为了避免多次“预检”请求,返回的是所有支持的方法
	header('Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS, PATCH, HEAD');
	
	// 表明服务器支持的所有头信息字段,不限于浏览器在“预检”中请求的字段(必需)
		# 对应在ajax中设置的setRequestHeader('Content-Type', ...);
	header('Access-Control-Allow-Headers: Content-Type, Content-Length, Authorization, Accept, X-Requested-With');	// 或者 *
	
	// 指定本次预检请求的有效期,单位为秒(可选)
	header('Access-Control-Max-Age: 1');
	
	// 处理传递过来的JSON字符串,转为PHP数组
	$json = json_decode($_POST['data'], true);
	
	echo 'Hello '.$json['name'].', 该消息来自: http://bbb.com';
?>
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值