一、简介

CORS:全称"跨域资源共享"(Cross-origin resource sharing)。CORS需要浏览器和服务器同时支持,才可以实现跨域请求,目前几乎所有浏览器都支持CORS,IE则不能低于IE10。CORS的整个过程都由浏览器自动完成,前端无需做任何设置,跟平时发送ajax请求并无差异。so,实现CORS的关键在于服务器,只要服务器实现CORS接口,就可以实现跨域通信。

【提示】跨域请求,数据可以正常的发送-响应,只是浏览器不会显示响应回来的内容。所以只有允许跨域,才能显示响应回来的数据内容。

    

此外,浏览器为了安全,不允许跨域请求,当然你可以关闭浏览器的禁止跨域请求的设置,但是不推荐!

二、请求类型

 CORS分为简单请求和非简单请求(需预检请求)两类

1. 简单请求

请求方式使用下列方法之一:
GET
HEAD
POST
 
Content-Type 的值仅限于下列三者之一:
text/plain
multipart/form-data
application/x-www-form-urlencoded

对于简单请求,浏览器会直接发送CORS请求,具体说来就是在header中加入origin请求头字段。同样,在响应头中,返回服务器设置的相关CORS头部字段,Access-Control-Allow-Origin字段为允许跨域请求的源。请求时浏览器在请求头的Origin中说明请求的源,服务器收到后发现允许该源跨域请求,则会成功返回,具体如下:

cors跨域接口 python cors实现跨域_spring

2. 非简单请求

使用了下面任一 HTTP 方法:
PUT
DELETE
CONNECT
OPTIONS
TRACE
PATCH
 
Content-Type 的值不属于下列之一:
application/x-www-form-urlencoded
multipart/form-data
text/plain

当发生符合非简单请求(预检请求)的条件时,浏览器会自动先发送一个options请求,如果发现服务器支持该请求,则会将真正的请求发送到后端,反之,如果浏览器发现服务端并不支持该请求,则会在控制台抛出错误,如下:

cors跨域接口 python cors实现跨域_字段_02

如果非简单请求(预检请求)发送成功,则会在头部多返回以下字段

Access-Control-Allow-Origin: http://localhost:3001  //该字段表明可供那个源跨域
Access-Control-Allow-Methods: GET, POST, PUT        // 该字段表明服务端支持的请求方法
Access-Control-Allow-Headers: X-Custom-Header       // 实际请求将携带的自定义请求首部字段

cors跨域接口 python cors实现跨域_cors跨域接口 python_03

红框标注的为预检请求发送的查询,服务端支持我们的请求后,将会发送我们真正的请求,图中绿框所示。可以看到,真正的请求响应头字段多处蓝框中所圈字段。这为服务器所支持cors请求类型和允许的自定义请求首部字段,以及支持跨域的源。

 

三、CORS字段介绍

1. Access-Control-Allow-Methods

该字段必需,它的值是逗号分隔的一个字符串,表明服务器支持的所有跨域请求的方法。注意,返回的是所有支持的方法,而不单是浏览器请求的那个方法。这是为了避免多次"预检"请求。

2. Access-Control-Allow-Headers

如果浏览器请求包括Access-Control-Request-Headers字段,则Access-Control-Allow-Headers字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段,不限于浏览器在"预检"中请求的字段。

3. Access-Control-Allow-Credentials

该字段与简单请求时的含义相同。

4. Access-Control-Max-Age

该字段可选,用来指定本次预检请求的有效期,单位为秒。上面结果中,有效期是20天(1728000秒),即允许缓存该条回应1728000秒(即20天),在此期间,不用发出另一条预检请求。

四、总结

总的来说,使用CORS简单请求,非常容易,对于前端来说无需做任何配置,与发送普通ajax请求无异。唯一需要注意的是,需要携带cookie信息时,需要将withCredentials设置为true即可。CORS的配置,完全在后端设置,配置起来也比较容易,目前对于大部分浏览器兼容性也比较好。CORS优势也比较明显,可以实现任何类型的请求,相较于JSONP跨域只能使用get请求来说,也更加的便于我们使用。
 

五、案例演示

跨域演示就是一个端口上的服务,向另一个端口的服务去请求资源。

   

springboot解决跨域请求的方式有多种,除了上面链接中的解决方式之外,还有其他的,例如:

1. 在允许跨域的方法上加@CrossOrigin注解

@RestController
public class HelloWorld {
    @CrossOrigin
    @RequestMapping("/abc")
    public Map<String,String> hello(){
        Map<String,String> map = new HashMap<>();
        map.put("msg","Hello pzz!");
        return map;
    }
}

2. 全局CORS配置

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

/**
 * @author zh
 * @ClassName cn.saytime.config.CORSConfiguration
 * @Description
 */
@Configuration
public class CORSConfiguration {

	@Bean
	public WebMvcConfigurer corsConfigurer() {
		return new WebMvcConfigurerAdapter() {
			@Override
			public void addCorsMappings(CorsRegistry registry) {
				registry.addMapping("/**")
						.allowedOrigins("http://domain.com", "http://domain2.com")
						.allowedMethods("GET", "POST", "DELETE", "PUT", "OPTIONS")
						.allowCredentials(false).maxAge(3600);
			}
		};
	}
}

3. 过滤器实现跨域(推荐)

import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;

@Configuration
public class CORSConfiguration {

    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(false);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

【提示】不要引错包!

 

扩展  Springboot应用的响应头有一点点不同

 

cors跨域接口 python cors实现跨域_cors跨域接口 python_04