为什么 Postman 在 JavaScript 中没有收到“请求的资源上不存在‘Access-ControlAllow-Origin’标头”错误

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跨域问题。