CORS
跨域处理
什么是跨域
跨域,是指浏览器不能执行其他网站的脚本。它是由浏览器的同源策略造成的,是浏览器对JavaScript实施的安全限制。浏览器从一个域名的网页去请求另一个域名的资源时,出现域名、端口、协议任一不同,都属于跨域。
CORS
Cross-Origin Resource Sharing (CORS) 是大多数浏览器 实现的 W3C规范,它允许以灵活的方式指定哪些类型的跨域请求可以访问, 而不是使用一些安全程度较低、功能较差的实现(如IFRAME或JSONP)
CORS的两种验证模式
- 简单请求:只发一次请求
- 预先请求:先发送一次预检请求,验证成功再发送真正请求
简单模式
简单请求模式下,浏览器直接发送跨域请求,并在请求头中携带 Origin 的头,表明这是一个跨域的请求。服务器端接到请求后,会根据自己的跨域规则,通过 Access-Control-Allow-Origin 响应头,来返回验证结果,如果验证成功则返回响应数据,验证失败不会返回数据
请求字段
Origin:表面当前请求所属的域
响应字段
Access-Control-Allow-Origin:表示允许访问的域,*表示允许所有
预先请求
浏览器在发现页面发出的请求非简单请求,并不会立即执行对应的请求代码,而是会触发预先请求模式。预先请求模式会先发送 Preflighted requests(预先验证请求),预检请求是一个 OPTIONS 请求,用于询问要被跨域访问的服务器,是否允许当前域名下的页面发送跨域的请求。在得到服务器的跨域授权后才能发送真正的 HTTP 请求。
OPTIONS 请求头部中会包含以下头部:Origin、Access-Control-Request-Method、Access-Control-Request-Headers。服务器收到 OPTIONS 请求后,设置 Access-Control-Allow-Origin、Access-Control-Allow-Method、Access-Control-Allow-Headers、Access-Control-Max-Age 头部与浏览器沟通来判断是否允许这个请求。如果 Preflighted requests 验证通过,浏览器才会发送真正的跨域请求。
请求字段
Access-Control-Request-Method:告知服务器实际请求使用的方法Access-Control-Request-Headers:告知服务器实际请求携带的首部字段列表,使用,分隔
响应字段
Access-Control-Allow-Origin:表示允许访问的域,*表示允许所有Access-Control-Allow-Methods:表示允许请求的方法列表,使用,分隔Access-Control-Request-Headers:表示服务器允许请求携带的字段列表,使用,分隔Access-Control-Expose-Headers:在跨域访问时,XMLHttpRequest对象的getResponseHeader()方法只能拿到一些最基本的响应头,Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma,如果要访问其他头,则需要服务器设置本响应头Access-Control-Max-Age:表示此次预检请求的有效期,在有效期内,同一请求不需要再次发送预检请求
附带身份凭证的请求
跨域请求时默认不会发送身份凭证信息,如Cookies,需要设置需要将XMLHttpRequest的withCredentials设置为true
当浏览器向服务器发送凭证信息时,如Cookies,如果服务端响应时没有携带[Access-Control-Allow-Credentials : true,浏览器不会将响应内容返回给发送者
注意:对于附带身份凭证的请求(通常是
Cookie),服务器不得设置Access-Control-Allow-Origin的值为“*”,否则请求将会失败
简单请求的条件
当请求同时满足下面三个条件时,CORS 验证机制会使用简单模式进行处理,不满足使用预先请求
请求方法是下列之一:
- GET
- HEAD
- POST
请求头中的 Content-Type 请求头的值是下列之一:
- application/x-www-form-urlencoded
- multipart/form-data
- text/plain
不超过以下请求头,Fetch规范定义了CORS安全头的集合(跨域请求中自定义的头属于安全头的集合)该集合为:
-
Accept
-
Accept-Language
-
Content-Language
-
Content-Type (需要注意额外的限制)
-
DPR
-
Downlink
-
Save-Data
-
Viewport-Width
-
Width
Spring MVC实现CORS
实现CORS的三种方法
- 使用@CrossOrigin注解
- 配置CorsMappings
- CorsFilter
使用@CrossOrigin注解
将@CrossOrigin注解添加到@Controller类上或@RequestMapping方法上,添加到类上可以统一处理类中所有接口的跨域问题
@CrossOrigin
@RequestMapping("/hello")
public String hello(){
return "hello";
}
属性
- allowCredentials:浏览器是否应当发送凭证信息,如Cookie,默认为false
- allowedHeaders:允许的请求头字段列表,默认为
* - exposedHeaders:指定哪些响应头可以暴露出来
- maxAge:预检请求的有效期,有效期内同一请求不再发送预检请求,默认1800秒
- methods:允许请求的方法,
*表示所有方法,默认为* - origins:允许的域,
*表示所有域
addCorsMappings
通过实现WebMvcConfigurer接口,重写addCorsMappings方法实现全局配置
public class MyWebMvcConfigurer implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry
//要处理的请求
.addMapping("/**")
.allowCredentials(true)
.allowedHeaders("*")
.allowedMethods("*")
.allowedOrigins("*")
.exposedHeaders("*")
.exposedHeaders("")
.maxAge(3600);
}
}
CosrsFilter
CorsFilter是Spring Web中提供的处理跨域的过滤器
总结
@CrossOrigin和addCorsMappings都会生成CorsConfiguration对象,根据这个对象创建CorsInterceptor拦截器,拦截器中调用DefaultCorsProcessor的processRequest方法完成对头部字段的设置
CorsFilter是一个Filter,是在Servlet之前进行过滤,CorsFilter需要手动创建CorsConfiguration对象进行配置,最后在doFilter方法中调用DefaultCorsProcessor的processRequest方法完成对头部字段的设置

浙公网安备 33010602011771号