浏览器与服务器发起跨域请求为何表现不同?CORS场景疑问
问题描述
我正在学习CORS相关知识,想理解其工作原理。SOP(同源策略)规定默认情况下跨域请求会被服务器拒绝。为此我在localhost搭建了两个服务器,分别运行在8081和8082端口:
8082服务器代码
const app = express(); //const cors = require('cors'); //app.use(cors({ origin: '*' })) app.listen(8082, function () { console.log('server running on 8082') }) app.get('/', (req, res) => { console.log({ host: req.headers.host }) console.log({ origin: req.headers.origin }) return res.json('good'); });
8081服务器代码
const app = express(); app.use(express.static('public')) app.listen(8081, function () { console.log('server running on 8081') }) app.get('/request', (req, res) => { fetch('http://localhost:8082/').then(res => res.json()).then(console.log) return res.end(); });
8081服务器静态页面(public/index.html)代码
<script> function t() { fetch('http://localhost:8082/').then(res => res.json()).then(console.log) } </script> <button onclick="t()"></button>
静态页面中的请求逻辑与/request接口完全一致,但点击按钮触发请求时会出现CORS错误,而调用/request接口时却能正常获取响应,请问这一差异的原因是什么?
原因解析
- 服务器端请求不受浏览器同源策略管控:8081的
/request接口里的fetch是在Node.js服务器环境中发起的,和浏览器没有关系。同源策略是浏览器为保护用户安全制定的规则,仅作用于浏览器环境下的前端代码,服务器之间的请求不受该规则限制,因此能正常获取8082的响应。 - 浏览器端请求必须遵守同源策略:静态页面中的
fetch是在用户浏览器中执行的,此时浏览器会严格执行CORS检查流程:- 发起跨域请求时,浏览器自动在请求头中加入
Origin字段,标记请求来源为http://localhost:8081; - 8082服务器未配置CORS相关响应头(如
Access-Control-Allow-Origin),返回的响应中没有允许跨域访问的标识; - 浏览器收到响应后,发现缺少允许当前源访问的CORS响应头,就会拦截该响应,抛出CORS错误,不会将响应内容返回给前端代码。
- 发起跨域请求时,浏览器自动在请求头中加入
核心区别就是请求发起的环境不同:服务器之间的请求不受浏览器规则限制,而浏览器中的前端代码跨域请求必须遵守SOP和CORS规则。
内容的提问来源于stack exchange,提问作者RTX
相关产品推荐
相关产品推荐

