什么是跨域问题?Spring Boot如何解决跨域问题?

 作者简介:大家好,我是码炫码哥,前中兴通讯、美团架构师,现任某互联网公司CTO,兼职码炫课堂主讲源码系列专题


代表作:《jdk源码&多线程&高并发》,《深入tomcat源码解析》,《深入netty源码解析》,《深入dubbo源码解析》,《深入springboot源码解析》,《深入spring源码解析》,《深入redis源码解析》等


联系qq:184480602,加我进群,大家一起学习,一起进步,一起对抗互联网寒冬。码炫课堂的个人空间-码炫码哥个人主页-面试,源码等

回答

跨域问题是一个前端和后端的通信问题,发生在浏览器窒息感同源策略时,限制了前端网页向其域名、协议、端口不同的服务器发生请求。比如前端的页面运行在 http://localhost:3000,而后端服务运行在 http://localhost:8080,这种情况下的请求就会触发跨域问题。

Spring Boot 提供了三种方式来解决跨域问题:

  1. 使用 @CrossOrigin 注解:适用于单个控制器或方法,指定允许跨域的来源。
  2. 全局配置 CORS:通过实现 WebMvcConfigurer 接口的 addCorsMappings 方法,进行全局跨域配置。
  3. 配置过滤器:自定义一个跨域过滤器,添加所需的 CORS 头。

详解

什么是跨域问题

跨域是指浏览器的同源策略限制了网页向其他域发送请求的行为。同源策略要求协议、域名、端口号必须一致。例如:

  • http://maxuan.net:80 和 https://``maxuan``.net:80 不同源(协议不同)。
  • http://``maxuan``.net:80 和 http://``maxuan``.net:8080 不同源(端口不同)。
  • http://``maxuan``.net和 http://api.``maxuan``.net不同源(域名不同)

当浏览器检测到跨域请求时,会自动触发 CORS(跨域资源共享,Cross-Origin Resource Sharing)检查。如果服务器没有正确设置 CORS 相关的响应头,浏览器会拦截请求,并报出跨域错误。

CORS 机制的工作方式

CORS 的核心在于浏览器与服务器之间通过 HTTP 头进行协商。具体过程如下:

简单请求

简单请求是指满足以下条件的 HTTP 请求:

  • 使用方法为 GETPOST 或 HEAD
  • 请求头只能包含以下字段:AcceptAccept-LanguageContent-LanguageContent-Type(仅限值为 application/x-www-form-urlencodedmultipart/form-data 或 text/plain)。

对于简单请求,浏览器直接发出请求,但需要服务器在响应头中返回:

Access-Control-Allow-Origin: http://localhost:3000

预检请求

当请求不满足简单请求的条件(如使用了复杂的请求头或方法),浏览器会先发送一个 OPTIONS 请求进行预检,确认服务器是否允许跨域。例如:

浏览器发出的预检请求:

OPTIONS /api/data HTTP/1.1
Origin: http://localhost:3000
Access-Control-Request-Method: POST
Access-Control-Request-Headers: Content-Type

服务器返回的预检响应:

HTTP/1.1 200 OK
Access-Control-Allow-Origin: http://localhost:3000
Access-Control-Allow-Methods: GET, POST, PUT, DELETE
Access-Control-Allow-Headers: Content-Type
Access-Control-Allow-Credentials: true

Spring Boot 如何解决跨域问题

使用 @CrossOrigin 注解

使用 @CrossOrigin 来标注某些方法允许跨域访问。例如:

@RestController
@RequestMapping("/mx")
public class MyController {

    @GetMapping("/getMxInfo")
    @CrossOrigin(origins = "http://localhost:3000") // 指定允许跨域的来源
    public String getMxInfo() {
        return "Hello, Cross-Origin!";
    }
}

origins 参数用于指定允许的来源,可以是具体的域名(如 http://maxuan.net:80,表示只允许指定域名跨域)或通配符(*,表示所有域名都可以跨域访问)。但是它只适用于那些特定的接口部分放开跨域。

全局配置 CORS

有些情况我们需要全局允许跨域,这个时候我们就需要全局配置跨域了,如下:

@Configuration
public class CorsConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**") // 匹配所有请求路径
                .allowedOrigins("http://localhost:3000") // 允许的来源
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的请求方法
                .allowedHeaders("*") // 允许的请求头
                .allowCredentials(true); // 允许发送 Cookie
    }
}
配置过滤器

在更加复杂的场景下,我们可能需要对请求头、响应头等进行更加细粒度的控制,此时我们就可以创建一个过滤器来实现:

@Component
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        httpResponse.setHeader("Access-Control-Allow-Origin", "http://localhost:3000");
        httpResponse.setHeader("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE");
        httpResponse.setHeader("Access-Control-Allow-Headers", "Content-Type, Authorization");
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        
        chain.doFilter(request, response);
    }
}

这种方式自由度比较高,但是实现难度比较大,复杂性高,比较适合那些复杂的需求场景。

浏览器的 CORS 是一种客户端安全保护机制,在实际开发中我们应该避免全局放开跨域,防止安全问题。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值