目录

跨域

为什么会有跨域

解决跨域问题的方案

CORS解决跨域

简单请求

特殊请求

springboot解决跨域


跨域

为什么会有跨域

跨域问题 是浏览器对于ajax请求的一种安全限制:

一个页面发起的ajax请求,只能是于当前页同域名的路径

 

解决跨域问题的方案

  • jsonp

    最早的解决方案,利用script标签可以跨域的原理实现

    缺点:

    • 需要服务器端的支持

    • 只能发起GET请求

  • nginx反向代理

    原理:利用nginx反向代理把跨域变为不跨域,支持各种请求方式

    缺点:

    • 需要在nginx进行额外配置,语义不清晰

  • CORS

    规范化的跨域请求解决方案,安全可靠

    优势:

    • 在服务端控制是否允许跨域,可自定义规则

    • 支持各种请求方式

    缺点:

    • 会产生额外的请求

 

CORS解决跨域

CORS是一个W3C标准,全称是“跨域资源共享”(Cross-orign resource sharing)

它允许浏览器向跨源服务器发出 XMLHttpRequest请求,从而克服了AJAX只能同源使用的限制。

CORS需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10

浏览器讲ajax请求分为两类:简单请求、特殊请求

 

简单请求

满足一下两大条件,就属于简单请求:

(1)请求方法是以下三种办法之一:

  • HEAD

  • GET

  • POST

(2)HTTP的头信息不超出以下几种字段:

  • Accept

  • Accept-Language

  • Content-Language

  • Last-Event-ID

  • Last-Event-ID

  • Content-Type只限于三个值:

    • application/x-www/form-urlencoded

    • multipart/form-data

    • text/plain

如果ajax请求是简单请求时,浏览器会在请求头重懈怠一个字段:Origin

// 当前请求属于哪个域(服务器根据这个只决定是否允许跨域)

Origin:http://manage.leyou.com

如果服务器允许跨域,会在响应头中携带一下信息:

// 可接受的域,是一个具体的域或者任意(*)

Access-Control-Allow-Orign:http://manage.leyou.com

// 是否允许携带Cookie

Access-Control-Allow-Credentials:true

 

特殊请求

不符合简单请求的条件,会被浏览器判定为特殊请求

特殊请求会在正式通信之前,增加一次HTTP查询请求,成为“预检”请求(preflight)

浏览器先询问服务器,当前网页所载的域名是否在服务器的许可名单之中,以及可以使用那些HTTP动词和头信息字段。只有得到肯定的答复,浏览器才会发出正式的XMLHttpRequest请求,否则就报错

HTTP Request Demo:

OPTIONS /user HTTP/1.1
Origin:http://manage.leyou.com
Access-Control-Request-Method:PUT
Access-Control-Request-Headers:X-Custom-Header
Host:api.leyou.com
Accept-Language:en-US

与简单请求相比,除了Origin以外,特殊请求多了两个头:

  • Access-Control-Request-Methods:接下来会用到的请求方式

  • Access-Control-Request-Headers:会额外用到的头信息

服务器如果许可跨域,会发出响应:

HTTP/1.1 200 OK
Date: ...
Server: ///
Access-Control-Allow-Origin: http://manage.leyou.com
Access-Control-Allow-Credentials: true
// 允许访问的方式
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
// 允许携带的头
Access-Control-Allow-Headers: x-Custom-Header
// 课次许可的有效时长,单位是s,过期之前无需再预检
Access-Control-Allow-Max-Age: 3600
Content-Type: text/html;charset=utf-8

 

springboot解决跨域

@EnableWebMvc
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
​
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 注册所有请求
                .allowedOrigins("*")
                .allowedMethods("GET", "POST", "PUT", "DELETE")
                .allowCredentials(false)
                .maxAge(3600);
    }
}