Spring Boot跨域问题

跨域请求

当我们从本身站点请求不同域名或端口服务所提供的资源时,就会发起跨域请求。

       例如,我们最常见的我们很多的css样式文件是会链接到某个公共CDN服务器上,而不是在本身的服务器上,这其实就是典型的一个跨域骑牛。但浏览器由于安全原因限制了在脚本(script)中发起的跨域HTTP请求。也就是说XMLHttpRequest和Fetch等是遵循“同源规则”的,即只能访问自己服务器的指定端口的资源(同意服务器不同端口也会视为跨域)。但这种限制在今天,我们的应用需要访问多种API或资源的时候就不能满足开发者的需求了,因此就产生了若干对于跨域的解决方案,JSONP是其中一种,但在今天来看主流的更彻底的解决方案是CORS(Cross-Origin Resource Sharing)

跨域资源共享(CORS)

       这种机制将跨域的访问控制权交给服务器,这样可以保证安全的跨域数据传输。现代浏览器一般会将CORS的支持封装在HTTP API之中(比如XMLHttpRequest和Fetch),这样可以有效控制使用跨域请求的风险。
       概况来说,这个机制是增加一系列的HTTP头来让服务器可以描述哪些源是允许使用浏览器来访问资源的。而且对于简单的请求和复杂请求,处理机制是不一样的。
       简单请求仅允许三个HTTP方法:GET,POST一级HEAD,另外只能支持若干header参数:Accept,Accept-Language,Content-Language,Content-Type(值只能是application/x-www-form-urlencoded、multipart/form-data 和 text/plain), DPR , Downlink , Save-Data , Viewport-Width 和 Width。
对于简单请求来说,比如下面这样一个简单的GET请求:从 http://me.domain 发起到 http://another.domain/data/blablabla 的资源请求

GET /data/blablabla/ HTTP/1.1
// 请求的域名
Host: another.domain
...//省略其它部分,重点是下面这句,说明了发起请求者的来源
Origin: http://me.domain

       应用了CORS的对方服务器返回的响应应该像下面这个样子,当然这里 Access-Control-Allow-Origin: * 中的 * 表示任何网站都可以访问该资源,如果要限制只能从 me.domain 访问,那么需要改成 Access-Control-Allow-Origin: http://me.domain

HTTP/1.1 200 OK
...//省略其它部分
Access-Control-Allow-Origin: *
...//省略其它部分
Content-Type: application/json

       那么对于复杂的请求怎么办?这需要一次预检请求和一次实际的请求,也就是说需要两次和对方服务器的请求/响应。预检请求是以option方法惊醒的,因为option方法不会改变任何资源,所以这个预检请求是安全的,它的职责在于发送实际请求将会使用的HTTP方法以及将要发送的header中将携带哪些内容,这样对方服务器可以根据预检请求的信息决定是否接受。

// 预检请求
OPTIONS /resources/post/ HTTP/1.1
Host: another.domain
...// 省略其它部分
Origin: http://me.domain
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

       服务器对预检请求的响应如下:

HTTP/1.1 200 OK
// 省略其它部分
Access-Control-Allow-Origin: http://me.domain
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: Content-Type
Access-Control-Max-Age: 86400
// 省略其它部分
Content-Type: text/plain

       接下来的正式请求就和上面的简单请求差不多了,就不赘述了。

在Spring Boot中启动CORS

       在Spring Boot的启动类中加入下面的代码:

@Bean
    @Order(Integer.MAX_VALUE)
    public CorsFilter corsFilter() {
        final UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        final CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        // 设置你要允许的网站域名,如果全允许则设为 *
        corsConfiguration.addAllowedOrigin("*");
        // 如果要限制 HEADER 或 METHOD 请自行更改
        corsConfiguration.addAllowedHeader("*");
        corsConfiguration.addAllowedMethod("*");
        urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);
        return new CorsFilter();
    }

如果加入上面的代码缺少jar包的话,在maven的pom文件中引入下面的依赖

<dependency>
    <groupId>com.thetransactioncompany</groupId>
    <artifactId>cors-filter</artifactId>
    <version>1.7.1</version>
</dependency>

<dependency>
    <groupId>com.thetransactioncompany</groupId>
    <artifactId>java-property-utils</artifactId>
    <version>1.9</version>
</dependency>

猜你喜欢

转载自blog.csdn.net/liuziteng0228/article/details/80473544