spring boot系列(七)跨域解决方案

2,432 阅读3分钟

以下内容来自于《Sping Boot+Spring Cloud+Vue+Element实战》第九章节:跨域解决方案

跨域是什么

现代浏览器为了保证数据安全,不同源的客户端甲苯在没有明确授权的情况下,不能读写对方浏览器的资源,这就是同源策略,这是浏览器安全的基础。

一个URL协议,域名端口都相同,这就是同源 以百度地址:http://www.baidu.com 为例,判断一下以下几种URL是否和百度地址同源

  • http://www.baidu.com/abc.html 协议,域名,端口相同,属于同源
  • https://www.baidu.com/ 协议不同(https),不同源
  • http://www.baidu.com:9090 端口不同,不同源
  • http://www.baiduABC.com/ 域名不同,不同源
  • ...

根据浏览器的同源策略,不同源的脚本是不能操作其它源的资源,要想获取其它源下的资源,就面临跨域问题。不同源之间的网站之间互相发送AJAX请求,就要通过跨域方案来解决。


CORS

为了解决浏览器跨域的问题,W3C提出了跨域资源共享方案,即CORS(Corss-Origin-Resources Sharing)。 CORS可以在不破坏现有的规则下,通过后端服务器(前端也可以实现)实现CORS接口,从而实现跨域通信。CORS将请求分文两类:简单请求非简单请求,分别对跨域通信进行支持。


简单请求

在CORS出现之前,发哦是哪个HTTP请求时在信息头(Headers)中不能包含任何自定义字段,而且HTTP信息不能超过以下几个字段:

  • Accept
  • Accept-Language
  • Content-Language
  • Last-Event-ID
  • Content-Type(只有application/x-www/form/urlencoded,multipart.form-data,text/plain 3种类型)

例如下面这样的一个简单请求的案例:

GET /test HTTP/1.1

Accept: * / *

Accept-Encoding: gzip,deflate,sdch,br

Origin: http://www.test.com

Host: www.test.com

对于简单请求,CORS的策略是请求时在头部增加一个Origin字段,服务器收到后,根据该字段判断是否允许该请求的访问

  • 允许访问,在HTTP头部中添加Access-Control-Allow-Origin字段,返回正确结果
  • 拒绝访问,头部信息中不加Access-Control-Allow-Origin

另外还有几个字段用于描述CORS返回结果:

  • Access-Control-Allow-Credentials:可选,用户是否可以发送,处理cookie
  • Access-Control-Expose-Headers:可选,可以让用户拿到的字段。

以下几个字段无论设置与否,用户均可以拿到:

  • Cache-Control
  • Content_language
  • Content-Type
  • Expries
  • Last-Modified
  • Pargma

非简单请求

对于非简单请求,浏览器会在真实请求发出前增加一次OPTION请求,称之为预检请求(preflight request)。预检请求将真实的请求信息(包括请求方法,自定义头部字段)添加到HTTP头部信息字段中,询问服务器是否允许。

例如下面一个GET请求

OPTIONS /test HTTP1.1

Orgin: http://www.test.com

Acess-Control-Request-Method: GET

Access-Contol-Reauest-Headers: X-Custom-Header

Host: www.test.com

与CORS相关的字段:

  • 请求使用HTTP方法:Acess-Control-Request-Method
  • 包含自定义字段:Access-Contol-Reauest-Headers

服务器收到请求时,需要分别对Origin,Acess-Control-Request-Method,Access-Contol-Reauest-Headers进行验证,验证通过后,会在返回的HTTP头部中添加:

  • Access-Control-Allow-Origin: Http://www.test.com
  • Acess-Control-Request-Methods: GET,PUT,POST,DELETE 真实请求允许的方法
  • Access-Contol-Reauest-Headers: X-Custom-Header 服务器允许使用的字段
  • Access-Contol-Reauest-Credentials: true 是否允许用户发送,处理cookie
  • Access-Contol-Reauest-Max-Age: 172800 预检请求的有效期,单位秒。有效期内,不会发送重复的预检请求

当通过了预检请求后,浏览器才会发送真实的请求到服务器。实现了跨域资源的访问。


CORS后端实现

后端CORS方案实现如下:

/**
 * 跨域实现
 */
@Configuration
public class CorsConfig implements WebMvcConfigurer {

    public void addCorsFilter(CorsRegistry registry){
        registry.addMapping("/**")                      // 允许跨域访问的路径
                .allowedOrigins("*")                    // 允许跨域访问的源 *:代表所有域名都可以跨域访问
                .allowedMethods("*")                    // 允许请求的方法  *:表示"GET","POST","PUT","DELETE"
                .maxAge(168000)                         // 预检间隔时间
                .allowedHeaders("*")                    // 允许头部携带任何信息
                .allowCredentials(true);                // 是否发送cookie true:允许携带cookie false:不允许
    }
}

本文使用 mdnice 排版