欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Spring Boot跨域问题

程序员文章站 2024-02-05 10:10:34
...

跨域请求

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

       例如,我们最常见的我们很多的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>