CORS: cross-origin resource sharing跨域资源共享
1.背景:浏览器为了安全,不让一个网站随便请求另一个网站的接口,而cors就是后端开"通行证",告诉浏览器这个来源可以访问我;
浏览器是如何判断请求是否跨域了呢?
浏览器有一个安全规则,叫同源策略(same-origin policy),同源就是协议+域名(非ip)+端口完全一样;只要有一个不一样就是跨域,不同源,浏览器默认禁止 AJAX/fetch 获取响应。
2.浏览器为什么要拦截跨域响应,同源策略的意义是什么,主要目的如下:
防止恶意网站:
偷偷访问你已登录的银行/公司后台
偷Cookie,Session,本地存储信息
伪造请求转账,删数据
所以跨域不是后端拦的,是浏览器拦的,后端其实已经收到请求并返回了数据,只是浏览器不交给前端JS
浏览器跨域限制的核心是JavaScript对跨源响应数据的读取权限,主要阻断接口请求(AJAX/Fetch)的数据获取,对静态资源仅限制内容读取与操作,通常不阻断加载本身;
请求发送后,若响应头缺少 Access-Control-Allow-Origin,浏览器直接丢弃响应体,JS 抛出异常
cors就是后端开"通行证",告诉浏览器这个来源可以访问我:
是一种让浏览器能安全访问不同服务器资源的技术规范;
解决什么问题:浏览器默认为了安全,不允许网页去请求别的域名的数据(比如 A 网站的代码不能直接拿 B 网站的数据),CORS就是用来解开这个限制的
不需要设置cors的场景:
1.前后端不分离且部署在同一域名同一端口的项目不需要设置cors;若前后端仍通过不同的端口或域名访问,此时存在跨域,需后端加响应头或网关处理(通过nginx或网关层统一转发屏蔽跨域问题);
2.前后端分离,部署在不同的域名端口,但是通过nginx或网关层统一转发请求到后端,屏蔽了跨域问题;
如果设置cors的话需要在响应头设置哪些信息呢:
核心响应头:
Access-Control-Allow-Origin:允许哪些来源访问我,必须返回
Access-Control-Allow-Methods:允许哪些请求方法,只有复杂请求(PUT/DELETE/ 自定义头)才需要。
Access-Control-Allow-Headers:允许前端带哪些自定义请求头 例如:token,Authorization
Access-Control-Allow-Credentials:是否允许带 Cookie
Access-Control-Max-Age:预检结果缓存时间,单位秒,规定时间内不再发 OPTIONS 预检请求,用于优化提升速度;
1.简单请求 vs 复杂请求:
1.1简单请求
满足下面所有条件就是简单请求:
方法:GET / HEAD / POST
请求头只有:Accept、Accept-Language、Content-Language、Content-Type
Content-Type 只能是:
application/x-www-form-urlencoded
multipart/form-data
text/plain
行为:直接发请求,不带OPTIONS预检。
1.2.复杂请求
只要有一条不符合,就是复杂请求:
PUT/DELETE/PATCH
自定义请求头(如 token、Authorization)
Content-Type: application/json
行为:先发OPTIONS预检请求 → 通过才发真实请求。
2.正常同域访问,浏览器会自动把Cookie带给后端;跨域时默认行为,浏览器不会自动带Cookie,需要设置Access-Control-Allow-Credentials 为true:
浏览器安全规范:允许携带凭证时,Origin不能是通配符 ,必须写具体域名,否则浏览器直接拒绝。
cors配置示例:
java
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**") //对所有接口生效
//.allowedOriginPatterns("*")
.allowedOriginPatterns("http://*.tb.com", "https://*.tb.com") //允许所有.tb.com子域名
.allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") //允许的请求方法
.allowedHeaders("*") //允许所有请求头
.allowCredentials(true) // 设置可以携带cookie等凭证
.maxAge(3600); //预检请求缓存1小时
}
}