切换语言为:繁体
Springboot解决跨域问题

Springboot解决跨域问题

  • 爱糖宝
  • 2024-10-23
  • 2044
  • 0
  • 0

前言

当我们创建好springboot项目写了的接口,正准备对接前端项目的时候,此时发现前端项目访问后端接口报错。

Springboot解决跨域问题

为什么会出现跨域

跨域的出现是因为浏览器的同源策略导致,浏览器出于安全的考量,防止一个网站对另一个网站的敏感信息。

同源的定义:

  • 协议(protocol): 如http,https

  • 域名(domain):example.com

  • 端口(port):8080等端口

当出现上述的存在不同的时候,即可判定为跨域。回到我们上述出现的问题,就是我们前端react项目正以http://localhost:3000的服务启动,用axios来访问后端接口服务http://localhost:8080 ,就很明显是端口不一样所导致的问题,此时才导致的跨域。

浏览器是怎么处理跨域请求

当我们前端构建的请求发送到后端的时候,浏览器会根据同源策略检查请求是否跨域 ,同时判断请求是否是简单请求 。对于简单请求和非简单请求处理方式会有所不同。

什么是简单请求

  • 请求方法 method: get,post,head 之一的

  • 被浏览器自动设置的的请求头header : 如ConnectionUser - Agent

  • 简单的请求头: AcceptAccept - LanguageContent - LanguageLast - ModifiedContent - Type(并且Content - Type的值仅限于application/x - www - form - urlencodedmultipart/form - datatext/plain

对于简单请求的发送,浏览器会准备直接发送请求 ,但在接收到响应后,浏览器会检查响应头中的Access - Control - Allow - Origin字段值,是否允许当前源地址的访问(地址如 http://localhost:3000或者通配符*),满足条件则可以将响应结果返回个前端,不满足则控制台爆出跨域错误。

什么是非简单请求

就是不满足简单请求的就是非简单请求,如请求方法为 PUT,DELETE等方法,请求头是 Authorization等字段

对于非简单请求的发送,浏览器的处理会发送一个预请求(OPTIONS请求)到服务器,OPTIONS请求就是为了判定是否允许请求,服务端会返回具体的是否允许的响应信息。如Access - Control - Allow - Methods(允许的请求方法)、Access - Control - Allow - Headers(允许的请求头)和Access - Control - Max - Age(预检请求的有效期)等字段。只有预检查得到结果是允许了之后,浏览器才会真正发送请求。

如何解决跨域

主要就是通过配置相关的CROS跨域信息,nginxspringboot都支持配置相关的跨域信息

  • Access - Control - Allow - Origin(允许前端访问源的地址)

  • Access - Control - Allow - Methods(允许前端访问的请求方法)

  • Access - Control - Allow - Headers(允许前端访问的请求头)

  • Access - Control - Expose - Headers(允许暴露给前端获取的请求头)

接口上的跨域配置

一种比较简便的方法,我们可以从后端的接口上进行处理,springboot有单独解决跨域处理的注解。将@CrossOrigin 注解到接口地址上/整个controller类上,配置上 origin信息

@RestController
public class TestController {
    // 方法上配置
    @CrossOrigin(origins = "*")
    @RequestMapping("/hello")
    public String hello() {
        return "hello";
    }
}

// 类上配置
@RestController
@CrossOrigin(origins = "*")
public class TestController {
}


这种配置属于单一的控制,书写便捷,但是缺点是对于其他接口需要一一添加,过于麻烦和繁琐。

使用拦截器

通过统一配置拦截器,对指定请求路径进行增加跨域配置的输出

@Configuration
public class WebCustomConfiguration implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        // 对于所有路径进行拦截,然后配置origin为*
        registry.addMapping("/**")
                .allowedOrigins("*");
    }
}


缺点: 如果项目有过滤器的时候,请求进入的顺序会出现不同,导致跨域信息被过滤器的重写或者修改了响应头。

使用统一的CORS过滤器(推荐)

使用 Spring Boot 提供的CorsFilter来统一配置跨域。在配置类中,可以通过@Bean方法来创建CorsFilter,并设置跨域相关的属性,如允许的源、允许的请求方法、允许的请求头等等

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 CorsConfig {
     @Bean
     public CorsFilter corsFilter() {
           CorsConfiguration config = new CorsConfiguration();
           config.addAllowedOrigin("*");
           config.addAllowedMethod("*");
           config.addAllowedHeader("*");
           config.addExposedHeader("*");
           // 是否允许证书 不再默认开启 
           // config.setAllowCredentials(true);
           UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
           source.registerCorsConfiguration("/**", config);
           return new CorsFilter(source);
     }
}


注意: 有了这个统一的CORS过滤器了,就不需要拦截器,避免混合配置。还有就是当你配置了allowCredentials 为true的时候,就必须指定allowOrigin为指定的地址,不能再只是通配符* 。

Access - Control - Allow - Credentials:这是一个跨域资源共享(CORS)相关的响应头。当它的值为true时,表示服务器允许浏览器发送带有凭据(如 Cookies、HTTP 认证信息等)的跨域请求。

请求结果

当我们配置完跨域信息后,reponse中的header会增加对于origin的配置信息返回。这个时候我们前端可以顺利的拿到后端数据并展示。

Springboot解决跨域问题

0条评论

您的电子邮件等信息不会被公开,以下所有项均必填

OK! You can skip this field.