Loading

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,需要设置需要将XMLHttpRequestwithCredentials设置为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方法完成对头部字段的设置

posted @ 2022-07-27 17:28  7shuo  阅读(80)  评论(0)    收藏  举报