什么是同源?
两个URL具有相同的协议(HTTPS)、相同的域名(www.example.com)和相同的端口(默认HTTP/HTTPS端口,即443),因此它们被认为是同源的,这个请求将被允许执行。
同源策略:旨在防止恶意网站通过JavaScript读取其他站点的敏感信息,例如cookies或其他存储在本地的数据。对于需要进行跨域通信的应用场景,可以通过CORS、JSONP等技术实现安全可控的数据交换。
非同源限制的三种行为:
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
什么是 CORS?
CORS 是一种 Web 应用程序的安全机制,用于限制跨域请求对目标服务器的访问。如果一个 Web 应用程序从一个源请求资源,而该资源位于另一个不同的源,那么跨域就发生了。CORS 机制允许服务器在响应中设置一组跨域访问控制头来告诉浏览器哪些跨域请求是允许的。
对于跨域问题,可以简单理解为:浏览器执行javascript脚本时,会检查这个脚本属于哪个页面,如果不是同源页面,就不会被执行。
CORS分类
浏览器将CORS分为了两类:简单请求和非简单请求。
1.简单请求
满足以下条件的请求,属于简单请求
(1) 请求方法是以下三种方法之一:
HEAD、GET、POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Content-Type (需要注意额外的限制)
DPR
Downlink
Save-Data
Viewport-Width
Last-Event-ID
Content-Type只能是下列三个值之一:
application/ x-www-form-urlencoded、multipart/form-data、text/plain
2.非简单请求
不满足上述的请求,属于非简单请求。浏览器将使用不同的处理方法。
浏览器对不同请求的处理
1.简单请求:
浏览器直接发出CORS请求。具体表现在,在请求头信息中增加一个Origin字段。Origin字段当中将说明本次请求来自哪个源。服务器在接收到该请求之后,根据Origin字段中的信息,决定是否同意该请求。
Origin: http: //api.bob.com
不管此次请求的源是否在许可范围内,服务器都会返回一个正常的HTTP响应。如果响应的头信息中 不包含 Access-Control-Allow-Origin字段,就表示此次请求的源不在许可范围内。
如果Origin指定的域名在服务器许可范围内,那么服务器返回的响应里,将返回Access-Control- Allow-Origin字段。
Access-Control-Allow-Origin: http: //api.bob.com
如果服务器要接受来自所有域的资源访问,那么这个字段对应的参数可以设置为“*“
2.非简单请求
非简单的CORS请求与简单CORS请求最重要的区别,是在发送实际请求之前,先发送一次预检请求。浏览器根据预检请求获知服务器是否允许本次请求。如果允许,才会发送实际请求。
预检请求
作用: 浏览器通过预检请求对服务器发出询问:此次访问源是否在服务器的许可名单之内,以及可以使用哪些请求方式和请求头字段。只有得到服务器的肯定答复之后,才会发出正式的请求。
请求:
浏览器发起一个使用OPTIONS方法的“预检请求”,预检请求当中携带Access-Control-Request-Method与 Access-Control-Request-Headers字段,前者表示实际请求将使用的方法;后者告知服务器实际请求将携带的自定义请求首部字段
OPTIONS /cors HTTP/1.1
Origin: http://api.bob.com
Access-Control-Request-Method: PUT
Access-Control-Request-Headers: X-Custom-Header
······
响应:
服务器将通过响应头,表明是否接受接下来客户端发起的实际请求。
Access-Control-Allow-Methods表示表示允许客户端使用GET, POST, PUT方法发出请求;
Access-Control-Allow-Headers 如果浏览器的请求头里包含了Access-Control-Request-Headers字段,那么服务器返回的头信息里就必须包含该字段。
Access-Control-Max-Age表示请求该响应的有效时间。单位秒(s)。在有效时间内浏览器无需再次发起预检请求。
······
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Access-Control-Max-Age: 86400
······
请求结果: 如果服务器通过了预检请求,那么在有效时间内的所有CORS请求头里都将包含一个Origin字段,服务器的响应头里也将包含Access-Control-Allow-Origin字段。
如何配置 CORS?
在 Spring Boot 中,可以通过配置 WebMvcConfigurerAdapter 来启用 CORS。以下是一个示例:
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/api/**")
.allowedOrigins("http://localhost:8080")
.allowedMethods("GET", "POST")
.allowedHeaders("header1", "header2", "header3")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}
全局 CORS 配置
实现WebMvcConfigurer 接口。
@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*")
.exposedHeaders("header1", "header2")
.allowCredentials(false).maxAge(3600);
}
}
addMapping
- 手动添加路由路劲。allowedOrigins
- 允许跨域请求的 URL。allowedMethods
- 允许跨域请求的 HTTP 方法。allowedHeaders
- 允许跨域请求的请求头。exposedHeaders
- 允许被客户端访问的响应头。allowCredentials
- 是否允许发送 cookie 等凭据信息。maxAge
- 响应的最大缓存时间(以秒为单位)。