SpringBoot处理跨域总结

解决跨域的五种方法

1、CorsFilter

新建一个类

@Configuration
public class CorsConfig {
    @Bean
    public CorsFilter corsFilter() {
        //1. 添加 CORS配置信息
        CorsConfiguration config = new CorsConfiguration();
        //放行哪些原始域
        //springboot版本为2.4.0以前写法
        config.addAllowedOrigin("*");
        //springboot版本为2.4.0以后写法
        config.setAllowedOriginPatterns(Collections.singletonList("*"));

        //查看项目的springboot版本
        //System.out.println(SpringBootVersion.getVersion());


        //是否发送 Cookie
        config.setAllowCredentials(true);
        //放行哪些请求方式
        config.addAllowedMethod("*");
        //放行哪些原始请求头部信息
        config.addAllowedHeader("*");
        //暴露哪些头部信息
        config.addExposedHeader("*");
        //2. 添加映射路径
        UrlBasedCorsConfigurationSource corsConfigurationSource = new UrlBasedCorsConfigurationSource();
        corsConfigurationSource.registerCorsConfiguration("/**",config);
        //3. 返回新的CorsFilter
        return new CorsFilter(corsConfigurationSource);
    }
}

2、重写 WebMvcConfigurer

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                //是否发送Cookie
                .allowCredentials(true)
                //放行哪些原始域
                .allowedOrigins("*")
                .allowedMethods(new String[]{"GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH"})
                .allowedHeaders("*")
                .exposedHeaders("*");
    }
}

3、使用注解

@RestController
@CrossOrigin(origins = "*")
public class CorsController {
    @RequestMapping("/cors")
    @CrossOrigin(origins = "*")
    public String cors() {
        return "cors";
    }
}

4、手动设置响应头

@RequestMapping("/cors")
public String cors(HttpServletResponse response) {
    response.addHeader("Access-Allow-Control-Origin","*");
    return "cors";
}

5、使用自定义filter

import org.springframework.context.annotation.Configuration;
import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@WebFilter(filterName = "CorsFilter ")
@Configuration
public class CorsFilter implements Filter {
    @Override
    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
        HttpServletResponse response = (HttpServletResponse) res;
        response.setHeader("Access-Control-Allow-Origin","*");
        response.setHeader("Access-Control-Allow-Credentials", "true");
        response.setHeader("Access-Control-Allow-Methods", "POST, GET, PATCH, DELETE, PUT, OPTIONS");
        response.setHeader("Access-Control-Max-Age", "3600");
        response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
        chain.doFilter(req, res);
    }
}

模拟跨域

跨域的拦截是浏览器行为,所以后端开发的时候不会遇到这个问题,只有在联调的时候才会发现,这种问题前端、后端都可以解决。前端通过代理请求同一域的一个接口,然后转发到后端。后端则通过在Response Header设置值解决。而后端本地测试跨域配置是否生效时比较麻烦,因为是浏览器问题,发布到测试环境流程长,所以需要本地也能复现跨域问题,其实也比较简单,只不过需要百度一些前端代码[狗头]

首先,先随便找一个网站,然后在Console向本地发送Http请求就能模拟跨域了。

// 普通请求
var xhr = new XMLHttpRequest();
xhr.open('OPTIONS', 'http://127.0.0.1:8080/test1');
xhr.send();
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

// GET请求
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/test1?a=1');
xhr.send();
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

// 携带header
var xhr = new XMLHttpRequest();
xhr.open('GET', 'http://127.0.0.1:8080/test1?a=1');
xhr.setRequestHeader('content-type', 'application/json');
xhr.setRequestHeader('signature', 'gaejhgkaehguiaehiuavoihvoihviehviehiohao');
xhr.send();
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

// POST请求
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://127.0.0.1:8080/test1?a=1');
xhr.setRequestHeader('content-type', 'application/json');
xhr.setRequestHeader('signature', 'gaejhgkaehguiaehiuavoihvoihviehviehiohao');
xhr.send("{a:1,b:2}");
xhr.onload = function(e) {
    var xhr = e.target;
    console.log(xhr.responseText);
}

跨域问题踩过的坑

这些问题主要是网上代码都是抄来抄去,有一些人抄的时候删了一些或者copy漏了,导致代码不全,然后又因为浏览器的一些机制导致了还是存在跨域问题,坑了后面的人。

踩坑一:没有允许OPTIONS请求跨域

比如用上面的方案二来处理跨域问题

乍一看没有什么问题,只是不支持OPTIONS请求,但是浏览器在处理跨域请求的时候,会先发送一个OPTIONS请求去检测服务是否允许跨域请求,然后再去请求服务要数据之类的。所以这里根本没解决,联调时还是会有跨域问题。

踩坑二:没有允许Credentials

场景:后端不允许前端传递用户凭证,但是前端请求的时候带上了,这时浏览器也会报跨域错误

用户凭证是用户登录之后,服务器下发的一些凭证,如cookie。在跨域请求中,浏览器并不会把cookie携带上,但是可以通过js代码携带上。

使用上面方案一,不允许用户凭证

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Spring Boot提供了多种方法来解决跨域问题,其中之一是通过实现WebMvcConfigurer接口来自定义处理器、拦截器、视图解析器、转换器以及设置跨域等。 具体而言,可以通过实现WebMvcConfigurer接口来配置跨域。其中,configureDefaultServletHandling方法是用来配置默认的Servlet处理,可以使用DefaultServletHandlerConfigurer的enable方法来开启默认的Servlet处理器,这样可以处理静态资源请求。另外,也可以通过enable方法指定默认的Servlet名称。 除了实现WebMvcConfigurer接口,还可以继承WebMvcConfigurationSupport类来实现定制化的配置。这个类提供了更加灵活的配置选项。 总结起来,通过实现WebMvcConfigurer接口或继承WebMvcConfigurationSupport类可以在Spring Boot中实现跨域功能。具体的配置方法可以根据实际需求选择适合的方式来进行配置。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [SpringBoot配置接口:WebMvcConfigurer](https://blog.csdn.net/JokerLJG/article/details/123224002)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *3* [【springboot】--跨域问题及webMvcConfigurer介绍](https://blog.csdn.net/xunmengyou1990/article/details/124557829)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值