跨域请求
一、什么是跨域请求
- 域=协议名+主机名+端口号,只有这三部分相同才能称为是相同的域访问。
http://www.php.cn:80和ftp://www.php.cn:80 不同域,协议不一样
http://www.php.cn:80和http://www.baidu.com:80 不同域,主机名不一样
http://www.php.cn:80和ftp://www.php.cn:8080 不同域,端口号不一样
http://www.php.cn:80/a.html和http://www.php.cn:80/b.js 同域
二、为什么要限制跨域请求
- 最主要的原因就是安全性问题,比如
CSRF
攻击。但是,既然不安全,为什么我们又要跨域请求呢?原因是有时为了服务器便于管理和减轻服务器压力,公司会把不同的资源放在不同的服务器上,这样就存在很多子域,这时比如A
子域的html
资源要去访问B
子域的图片资源就会出现跨域请求了。
三、通过 CORS 方式解决简单跨域请求
CORS
:全称”跨域资源共享”(Cross-origin resource sharing
)CORS
就是跨源资源共享,这种机制利用浏览器所支持的向跨源服务器发出xmlhttprequest
请求,所以我们只需要做的是在服务器端判断是否允许这个域访问,剩下的浏览器会自动做好,添加一些头信息。CORS 需要浏览器和服务器同时支持,才可以实现跨域请求,目前几乎所有浏览器都支持 CORS,IE 则不能低于 IE10。CORS 的整个过程都由浏览器自动完成,前端无需做任何设置,跟平时发送 ajax 请求并无差异。实现 CORS 的关键在于服务器,只要服务器实现 CORS 接口,就可以实现跨域通信。
Access-Control-Allow-Origin: http://localhost:80 //该字段表明可供那个源跨域
Access-Control-Allow-Methods: GET, POST, PUT // 该字段表明服务端支持的请求方法
Access-Control-Allow-Headers: X-Custom-Header // 实际请求将携带的自定义请求首部字段
CORS 字段介绍
1.Access-Control-Allow-Methods
该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次”预检”请求。
2.Access-Control-Allow-Headers
如果浏览器请求包括 Access-Control-Request-Headers 字段,表明服务器支持的所有头信息字段,不限于浏览器在”预检”中请求的字段。
3.Access-Control-Allow-Credentials
4.Access-Control-Max-Age
该字段可选,用来指定本次预检请求的有效期,单位为秒。上
四、通过 JSONP 方式处理跨域请求
- 只要服务端提供的 js 脚本是动态生成,这样调用者可以传一个参数过去告诉服务端 “我想要一段调用某函数的 js 代码,请你返回给我”,于是服务器就可以按照客户端的需求来生成动态 js 脚本并响应。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<button>跨域请求-JSONP</button>
<script>
// 1. 准备好回调处理函数
function handle(jsonData) {
console.log(jsonData);
var data = JSON.parse(jsonData);
console.log(data);
// 将接口返回的数据渲染到页面中
var ul = document.createElement("ul");
ul.innerHTML += "<li>" + data.title + "</li>";
ul.innerHTML += "<li>姓名:" + data.user.name + "</li>";
ul.innerHTML += "<li>邮箱: " + data.user.email + "</li>";
document.body.appendChild(ul);
}
// 2. 点击按钮发起一个基于JSONP的跨域请求
var btn = document.querySelector("button");
btn.addEventListener(
"click",
//动态生成js
function () {
//生成一个元素
var script = document.createElement("script");
//添加一个src地址
script.src = "http://php.edu/0522/test2.php?jsonp=handle&id=3";
//添加到head中
document.head.appendChild(script);
},
false
);
</script>
</body>
</html>
五、总结
跨域请求的处理方式有很多,除了上面提的 JSONP
策略和 CORS
策略,还有通过 window.name
属性等方式解决跨域请求。总的来说,使用 CORS
简单请求,非常容易,对于前端来说无需做任何配置,与发送普通 ajax 请求无异。唯一需要注意的是,需要携带 cookie
信息时,需要将 withCredentials
设置为 true
即可。CORS
的配置,完全在后端设置,配置起来也比较容易,目前对于大部分浏览器兼容性也比较好。CORS
优势也比较明显,可以实现任何类型的请求,相较于 JSONP 跨域只能使用 get 请求来说,也更加的便于我们使用。
但 ajax 和 jsonp 其实本质上是不同的东西。ajax 的核心是通过 XmlHttpRequest 获取非本页内容,而 jsonp 的核心则是动态添加