springboot解决CORS跨域问题

一、跨域现象

1.在axios请求中传参,在后端不设置CORS的时候,控制器信息为:


浏览器报错

2.CORS是什么东西?
CORS是一个W3C标准,全称是"跨域资源共享"(Cross-origin resource sharing)。

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

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

整个CORS通信过程,都是浏览器自动完成,不需要用户参与。对于开发者来说,CORS通信与同源的AJAX通信没有差别,代码完全一样。浏览器一旦发现AJAX请求跨源,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感觉。

因此,实现CORS通信的关键是服务器。只要服务器实现了CORS接口,就可以跨源通信。

跨域的体现,在于它的域名不同或者端口不同,但要注意以下的形式为非跨域模式
http://www.example.com/index.html ==> http://www.example.com/login.html

二、springboot的两种解决方式

1.局部设置

@CrossOrigin(origins = "http://localhost:8081", maxAge = 3600)
直接在控制器方法前注解,设置可以跨域的源ip和端口,以及预检有效期maxAge等参数。

  • 对控制器中单个方法设置跨域
    /**
     * @param request request
     * @return Map
     * @throws IOException Exception
     */
    @CrossOrigin(allowCredentials = "true", allowedHeaders = "*")
    @PostMapping("/uploadCourse")
    public ResultData uploadCourse(HttpServletRequest request) throws IOException {
          some code    ……………… 
    }
  • 对整个控制器设置跨域
@RestController
//实现跨域注解
//origin="*"代表所有域名都可访问
//maxAge飞行前响应的缓存持续时间的最大年龄,简单来说就是Cookie的有效期 单位为秒
//若maxAge是负数,则代表为临时Cookie,不会被持久化,Cookie信息保存在浏览器内存中,浏览器关闭Cookie就消失
@CrossOrigin(origins = "*",maxAge = 3600)
public class UserController {
    @Resource
    private IUserFind userFind;

    @GetMapping("finduser")
    public User finduser(@RequestParam(value="id") Integer id){
        //此处省略相应代码
    }
}

2.全局设置

编写配置类,配置全局的CORS设置。

@Configuration
public class MyCorsConfig { 
    /** 
     * corsFilter
     * @Description
     * @param 
     * @return org.springframework.boot.web.servlet.FilterRegistrationBean
     * @Date 2018/7/3 16:55
     */
    @Bean
    public FilterRegistrationBean corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        source.registerCorsConfiguration("/**", config);
        FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
        bean.setOrder(0);
        return bean;
    }
}

三、问什么会多一次options请求

image.png

出于安全原因,浏览器限制从脚本内发起的跨源HTTP请求。当一个资源从与该资源本身所在的服务器不同的域或端口请求一个资源时,资源会发起一个跨域 HTTP 请求。摘自http访问控制

options叫做预检请求,就是查看是否可以或者允许跨域请求,以下是MDN的解释。

跨域资源共享标准新增了一组 HTTP 首部字段,允许服务器声明哪些源站有权限访问哪些资源。另外,规范要求,>对那些可能对服务器数据产生副作用的 HTTP 请求方法(特别是 GET 以外的 HTTP 请求,或者搭配某些 MIME 类型>的 POST 请求),浏览器必须首先使用 OPTIONS 方法发起一个预检请求(preflight request),从而获知服务端是>否允许该跨域请求。服务器确认允许之后,才发起实际的 HTTP 请求。在预检请求的返回中,服务器端也可以通知>客户端,是否需要携带身份凭证(包括 Cookies 和 HTTP 认证相关数据)。

也就是在前端真实发送请求时会发送一个预检请求,由他的返回来告知浏览器服务是否允许跨域请求,若不允许则会报CORS的错误。

扩展阅读

CORS https://www.cnblogs.com/chris-oil/p/8042677.html
springboot的其他几种方式 https://blog.csdn.net/ZYC88888/article/details/86534515

你可能感兴趣的:(springboot解决CORS跨域问题)