1. 什么是CORS
CORS(Cross-Origin Resource Sharing)跨域资源共享指的是,一个域名下的Web应用,可以通过JavaScript对其它域名下的资源进行访问。由于浏览器的同源策略,限制了Web应用不能够访问其它域名下的资源,而CORS能够实现跨域访问。
1.1 同源策略是什么
同源策略(Same-origin policy)是浏览器对Javascript施加的一种安全限制,它是用来限制一个脚本对另一个脚本的访问,它要求脚本必须来源于同一个域,才能够互相访问对方的资源。
// 跨域访问其他域名下的API,会出现跨域访问限制
fetch('https://www.example.com/api/data')
// No 'Access-Control-Allow-Origin' header is present on the requested resource.
// Origin 'http://localhost:3000' is therefore not allowed access.
1.2 CORS的工作原理
当浏览器发现AJAX请求跨域时,会在http头信息中添加Origin
字段,指定请求的来源域名,服务器接收到请求后,在http头信息中添加Access-Control-Allow-Origin
字段,指定允许访问的域名,从而完成跨域操作。
// 响应头中添加'Access-Control-Allow-Origin'字段,解决跨域问题
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
next()
})
2. Postman请求时的跨域问题
由于Postman是独立的应用程序,不受浏览器的同源策略限制,因此在通过Postman发送AJAX请求时,不会出现CORS跨域访问限制。但在JavaScript中使用AJAX时,会受到同源策略的限制。
2.1 XMLHttpRequest的跨域限制
XMLHttpRequest是浏览器内置的AJAX接口,它不能访问另一个域下的资源,即浏览器的同源策略限制了XMLHttpRequest只能请求同源下的资源。因此,XHR不能跨域请求资源,从而导致出现“请求的资源上不存在‘Access-Control-Allow-Origin’标头”错误。
// XHR不能跨域请求资源,会出现跨域访问限制
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https://www.example.com/api/data', true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
xhr.send();
2.2 fetch的跨域限制
fetch是ES6新增的网络请求接口,同样受到同源策略的限制。在发起跨域请求时,fetch会自动添加Origin
头信息,告诉服务器请求的来源。服务器在收到请求后,会进行CORS处理,并在Access-Control-Allow-Origin
头信息中返回允许访问的域名。
// fetch发起跨域请求时,会受到同源策略的限制
fetch('https://www.example.com/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err))
3. 怎样解决CORS跨域访问限制
由于浏览器的同源策略限制了Web应用不能够访问其它域名下的资源,因此必须通过CORS进行跨域访问。下面介绍两种常用的解决CORS跨域问题的方法。
3.1 服务器端设置响应头
最常用的方法是,服务器端设置响应头信息Access-Control-Allow-Origin
,告知浏览器允许哪些域名访问。
// 服务器端设置响应头信息
app.use(function (req, res, next) {
res.setHeader('Access-Control-Allow-Origin', 'http://localhost:3000')
next()
})
3.2 使用代理服务器
使用代理服务器(Proxy Server)是另一种跨域访问的方法。在浏览器端向代理服务器发送请求,由代理服务器再转发请求并返回响应,浏览器在获取响应时就不存在CORS跨域访问限制了。
// 使用代理服务器解决跨域问题
fetch('http://localhost:3001/api/data')
.then(response => response.json())
.then(data => console.log(data))
.catch(err => console.error(err))
4. 总结
CORS跨域资源共享是解决Web应用跨域访问的重要方法,它通过CORS协议实现,可以在服务端设置响应头信息,或使用代理服务器等方式来解决CORS跨域问题。