网站首页 > 技术文章 正文
当你在浏览器控制台看到那串刺眼的红色错误——"Access to XMLHttpRequest at 'https://api.example.com' from origin 'https://yourwebsite.com' has been blocked by CORS policy",是不是瞬间感觉头皮发麻?这个被前端开发者戏称为"跨域魔咒"的问题,其实背后藏着浏览器最严格的安全卫士——同源策略。今天咱们就来扒开这个"保安系统"的工作手册,让你下次遇到CORS错误时能淡定地说:"小场面,我知道怎么搞定"。
浏览器的"门禁系统":同源策略到底在防什么?
现代浏览器就像个戒备森严的写字楼,每个网页都是一间办公室。同源策略就是这里的门禁规则:只有协议、域名、端口三者完全相同的"访客"(请求)才能自由通行。举个例子,
https://www.example.com:443和http://www.example.com:80虽然只差一个s和端口号,在浏览器眼里就是两个完全不同的"公司",想要串门?没门!
你可能会问:"浏览器至于这么较真吗?"还真至于。没有同源策略的保护,黑客的脚本可以轻松读取你银行账户页面的Cookie,或者伪装成你在社交网站上发帖。2018年某电商平台就因同源策略配置不当,导致用户收货地址被恶意网站获取,这个教训至今让开发者记忆犹新。
CORS:给跨域请求办"通行证"
既然同源策略这么严格,那不同网站之间怎么合法交流?这就需要CORS(跨域资源共享)这个"通行证系统"登场了。简单说,CORS就是服务器告诉浏览器:"这个域名的请求我认,你让它进来吧"。
但浏览器这个"保安"特别谨慎,不是所有请求都直接放行。它会把请求分成两类:
- 简单请求:像GET、POST这类"老实本分"的请求,会直接发送,服务器在响应头里加上Access-Control-Allow-Origin: https://yourwebsite.com就行
- 预检请求:如果请求带了自定义头或者用了PUT、DELETE等"特殊动作",浏览器会先派个"侦察兵"(OPTIONS请求)去问服务器:"我这请求能过不?"服务器同意后才会发送真正的请求
这个过程就像你去别人家做客:简单请求是"打个招呼就进门",预检请求则是"先打电话问问主人在不在家"。
那些年我们踩过的CORS坑
就算懂了原理,实际开发中还是会被CORS折磨得怀疑人生。看看这些经典错误你是不是似曾相识:
No '
Access-Control-Allow-Origin' header:这是最常见的"拦路虎"。后端开发者拍着胸脯说"我配了啊",结果一看代码——
Access-Control-Allow-Origin设成了*却同时用了Cookie,浏览器直接判定"通行证无效"。记住:带Cookie的跨域请求,服务器必须明确指定域名,不能用通配符。
预检请求被拒绝:前端开发者兴冲冲写了个带X-Token头的请求,结果控制台报错。原因很简单:服务器没在
Access-Control-Allow-Headers里加上这个自定义头,就像你拿着门禁卡却忘了录指纹。
凭据丢失问题:明明前端设置了withCredentials: true,服务器也配了Allow-Credentials,请求还是失败。这时不妨看看服务器是不是同时设置了
Access-Control-Allow-Origin: *——浏览器规定,带凭据的请求和通配符域名是水火不容的。
搞定CORS的实战秘籍
解决CORS问题就像开锁,找对钥匙很重要。这里有几套"万能钥匙"供你选择:
后端配置是根本:不管前端怎么折腾,最终还得靠服务器松口。不同语言有不同的配置方式,但核心都是设置那几个关键响应头:
- Node.js(Express):
app.use((req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', 'https://yourwebsite.com');
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, X-Token');
res.setHeader('Access-Control-Allow-Credentials', 'true');
next();
});
- Java(Spring Boot):
@Configuration
public class CorsConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("https://yourwebsite.com")
.allowedMethods("*")
.allowedHeaders("*")
.allowCredentials(true);
}
}
前端代理是权宜之计:开发环境下,用Webpack或Vite配置代理服务器,把跨域请求伪装成同源请求:
// vite.config.js
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'https://api.example.com',
changeOrigin: true,
rewrite: path => path.replace(/^\/api/, '')
}
}
}
})
JSONP是老古董:虽然只能支持GET请求,但在某些奇葩环境下(比如IE8),JSONP还是能救急。原理就是利用<script>标签不受同源策略限制的特性,不过现在已经基本被CORS取代了。
生产环境的CORS最佳实践
上线前这些细节千万不能忽略:
- 别用通配符:明确指定允许的域名,Access-Control-Allow-Origin: *虽然省事,但就像给大楼所有门都配了一把钥匙
- 限制请求方法:别偷懒写allowedMethods: "*",只开放需要的HTTP方法
- 预检缓存:设置Access-Control-Max-Age缓存预检请求结果,减少不必要的OPTIONS请求
- CDN也要配置:如果静态资源放在CDN上,别忘了在CDN控制台也配置CORS规则
浏览器的同源策略就像一把双刃剑,既保护了用户安全,也给开发者添了不少麻烦。但只要搞懂它的工作原理,掌握CORS的配置技巧,下次再遇到跨域错误,你就能像拆弹专家一样从容应对。记住,每个红色的CORS错误提示背后,都藏着浏览器默默守护安全的良苦用心——虽然这份守护有时确实让人想砸键盘。
猜你喜欢
- 2025-07-09 跨域资源的共享(CORS)N种用法(跨域资源共享的缩写是?)
- 2025-07-09 Axios CORS 问题处理(axios has been blocked by cors policy)
- 2025-07-09 JavaScript-JavaScript 219
- 2025-07-09 前端面试题《AJAX》(前端面试题js)
- 2025-07-09 某水果网站逆向分析(水果销售网站的设计与实现)
- 2025-07-09 揭秘:视频播放网站如何精准记录用户观看进度
- 2025-07-09 国外友人开创Python模拟登陆神库,完美修改它为咱们所用
- 2025-07-09 Ajax异步JavaScript和XML(ajax异步原理)
- 2025-07-09 2021年超详细的java学习路线总结—纯干货分享
- 2025-07-09 webapi 全流程(webapi怎么部署)
- 1509℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 533℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 496℃MySQL service启动脚本浅析(r12笔记第59天)
- 475℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 473℃启用MySQL查询缓存(mysql8.0查询缓存)
- 453℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 432℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 430℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- c++中::是什么意思 (83)
- 标签用于 (65)
- 主键只能有一个吗 (66)
- c#console.writeline不显示 (75)
- pythoncase语句 (81)
- es6includes (73)
- windowsscripthost (67)
- apt-getinstall-y (86)
- node_modules怎么生成 (76)
- chromepost (65)
- c++int转char (75)
- static函数和普通函数 (76)
- el-date-picker开始日期早于结束日期 (70)
- js判断是否是json字符串 (67)
- checkout-b (67)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- & (66)
- java (73)
- js数组插入 (83)
- linux删除一个文件夹 (65)
- mac安装java (72)
- eacces (67)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)