当前位置:首页 > 技术分析 > 正文内容

京东大佬问我,SpringBoot为什么会出现跨域问题?如何解决?

ruisui884个月前 (03-07)技术分析16

京东大佬问我,SpringBoot为什么会出现跨域问题?如何解决?

首先,我得先理解什么是跨域问题,然后才能解释为什么会出现,接着再讲Spring Boot的解决方法。好,先从头开始思考。

跨域问题,应该是指浏览器出于安全考虑,限制不同源之间的请求。同源策略,对吧?比如,如果前端应用运行在http://localhost:8080,而后端API在http://localhost:8081,这时候前端发请求到后端就会被浏览器阻止,因为端口不同,属于不同源。这时候就会出现跨域问题,也就是CORS(Cross-Origin Resource Sharing)问题。

那为什么会有这个问题呢?主要是为了安全。比如,防止恶意网站通过脚本访问另一个网站的敏感数据。比如,如果没有同源策略,一个恶意网页的脚本可以随意访问用户的银行网站,如果用户已经登录的话,这样会非常危险。所以浏览器默认阻止跨域请求,除非服务器明确允许。

接下来是Spring Boot如何解决这个问题。Spring Boot中通常有几种方式处理跨域问题。我记得可以通过配置CORS,或者在Controller中使用注解,或者全局配置的方式。

首先,使用@CrossOrigin注解。这个可以加在Controller类或者方法上,指定允许的来源、方法等。比如在某个RestController的方法上加@CrossOrigin(origins = "http://localhost:8080"),这样这个方法就可以被该源访问。不过这种方法可能比较繁琐,如果有很多Controller的话,每个都要加,不太方便。

另一种方式是全局配置,通过定义一个WebMvcConfigurer的Bean,然后重写addCorsMappings方法。这样可以在一个地方统一配置,适用于整个应用。例如:

@Configuration

public class CorsConfig implements WebMvcConfigurer {

@Override

public void addCorsMappings(CorsRegistry registry) {

registry.addMapping("/**")

.allowedOrigins("http://localhost:8080")

.allowedMethods("GET", "POST", "PUT", "DELETE")

.allowedHeaders("*")

.allowCredentials(true)

.maxAge(3600);

}

}

这样配置的话,所有路径都允许来自http://localhost:8080的跨域请求,允许的HTTP方法包括GET、POST等,允许所有头,允许携带凭证,预检请求缓存时间1小时。这可能是一个比较全面的配置方式。

还有一种方式是通过过滤器(Filter)来处理,在过滤器中设置响应头。比如,创建一个CorsFilter,然后在doFilter方法里设置
Access-Control-Allow-Origin等头信息。不过这种方法可能比较底层,不如使用Spring提供的配置方式方便。

但需要注意,如果项目中用了Spring Security,可能还需要在Security配置中允许跨域,因为Spring Security的过滤器链可能会覆盖这些设置。这时候可能需要同时配置CORS和Spring Security。例如,在Spring Security的配置中启用cors,并引用上面定义的Cors配置源。

比如,在Spring Security配置类里加上:

@EnableWebSecurity

public class SecurityConfig extends WebSecurityConfigurerAdapter {

@Override

protected void configure(HttpSecurity http) throws Exception {

http.cors().and()

// 其他配置

.csrf().disable(); // 如果需要的话,关闭CSRF

}

@Bean

CorsConfigurationSource corsConfigurationSource() {

CorsConfiguration configuration = new CorsConfiguration();

configuration.setAllowedOrigins(Arrays.asList("http://localhost:8080"));

configuration.setAllowedMethods(Arrays.asList("GET","POST","PUT","DELETE"));

configuration.setAllowedHeaders(Arrays.asList("*"));

configuration.setAllowCredentials(true);

UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

source.registerCorsConfiguration("/**", configuration);

return source;

}

}

不过这样的话,可能和之前的全局配置冲突,或者需要统一配置方式。可能更建议使用WebMvcConfigurer的方式,或者在Spring Security中配置。

总结来说,Spring Boot解决跨域的主要方法有两种:使用@CrossOrigin注解局部配置,或者通过全局配置类实现WebMvcConfigurer来统一处理。如果项目集成了Spring Security,还需要确保Security的配置允许CORS。

那代码详细说明的话,应该给出这两种方式的示例,并解释各个参数的作用。比如在全局配置中,allowedOrigins可以设置多个源,allowedMethods指定允许的HTTP方法,allowCredentials是否允许发送cookie等。maxAge则是预检请求的有效期,减少预检请求的次数。

另外,需要注意allowedOrigins不能使用通配符*和allowCredentials(true)同时存在,否则浏览器会拒绝,因为这样会有安全风险。如果允许凭证的话,必须明确指定具体的源,而不能是通配符。

比如,如果设置.allowedOrigins("*")和.allowCredentials(true),启动应用时会报错,或者浏览器拒绝请求。这时候需要明确指定允许的源,比如具体的域名或IP+端口。

可能还要提到,在开发环境中为了方便,可能会允许所有源,但在生产环境中应该严格限制。例如:

.allowedOrigins("http://localhost:8080", "https://production-domain.com")

这样分开环境配置会更安全。

最后,代码示例需要详细,包括配置类的写法,可能遇到的问题,比如Spring Security的影响,以及常见错误配置的解决方法。

现在我需要把这些思路整理成一个连贯的回答,结构清晰,分点说明,代码示例正确,并解释每个参数的作用。同时,指出可能遇到的坑,比如Spring Security的配置,通配符和凭证的冲突等。

跨域问题是由浏览器的同源策略引起的安全机制,限制了不同源(协议、域名、端口不同)之间的资源交互。Spring Boot 提供了多种解决方案,以下是详细说明:


一、为什么会出现跨域问题?

  1. 同源策略(Same-Origin Policy):浏览器默认阻止跨域请求,防止恶意网站读取敏感数据。
  2. CORS(跨域资源共享):服务器需显式声明允许的源、方法和头信息,否则浏览器会拦截响应。

二、Spring Boot 解决跨域的三种方法

1. 使用@CrossOrigin注解(局部配置)

在 Controller 类或方法上添加注解,指定允许的源、方法等。

@RestController
public class MyController {
    @CrossOrigin(origins = "http://localhost:8080")
    @GetMapping("/hello")
    public String hello() {
        return "Hello, CORS!";
    }
}
  • 参数说明
    • origins:允许的源列表,如 {"http://site1.com", "http://site2.com"}。
    • methods:允许的 HTTP 方法,如 RequestMethod.GET。
    • allowedHeaders:允许的请求头,默认为 *(所有)。
    • allowCredentials:是否允许发送 Cookie(默认 false)。

2. 全局配置(推荐)

通过实现 WebMvcConfigurer 接口,统一配置所有接口的 CORS 规则。

@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
            .allowedOrigins("http://localhost:8080") // 允许的源
            .allowedMethods("GET", "POST", "PUT", "DELETE") // 允许的方法
            .allowedHeaders("*") // 允许所有头
            .allowCredentials(true) // 允许凭证(如 Cookie)
            .maxAge(3600); // 预检请求缓存时间(秒)
    }
}
  • 关键点
    • allowedOrigins 和 allowCredentials(true) 同时使用时,不能设为 *,需指定具体源。
    • maxAge 减少预检请求次数,提升性能。

3. 结合 Spring Security 的配置

若项目集成 Spring Security,需额外配置以启用 CORS。

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and() // 启用 CORS
            .csrf().disable() // 根据需求关闭 CSRF
            .authorizeRequests()
            .anyRequest().authenticated();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowedOrigins(Arrays.asList("http://localhost:8080"));
        config.setAllowedMethods(Arrays.asList("GET", "POST"));
        config.setAllowedHeaders(Arrays.asList("*"));
        config.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }
}

三、常见问题与注意事项

  1. 通配符与凭证冲突
  2. 错误配置:.allowedOrigins("*").allowCredentials(true)。
  3. 正确做法:指定具体源,如 .allowedOrigins("http://trusted-domain.com")。
  4. 环境区分
  5. 开发环境可放宽限制,生产环境应严格限制源。
  6. 预检请求(Preflight)
  7. 复杂请求(如 Content-Type: application/json)会先发送 OPTIONS 请求,确保服务器支持 CORS。

通过以上方法,Spring Boot 可灵活解决跨域问题,开发者可根据项目需求选择局部或全局配置。

扫描二维码推送至手机访问。

版权声明:本文由ruisui88发布,如需转载请注明出处。

本文链接:http://www.ruisui88.com/post/2563.html

分享给朋友:

“京东大佬问我,SpringBoot为什么会出现跨域问题?如何解决?” 的相关文章

Win+Ubuntu缝合怪:第三方开发者推出“Wubuntu”Linux发行版

IT之家 2 月 26 日消息,一位第三方开发者推出了一款名为“Wubuntu”的缝合怪 Linux 发行版,系统本身基于 Ubuntu,但界面为微软 Windows 11 风格,甚至存在微软 Windows 徽标。据介绍,这款 Wubuntu 发行版旨在为习惯使用 Windows 11 的用户打造...

理解virt、res、shr之间的关系(linux系统篇)

前言想必在linux上写过程序的同学都有分析进程占用多少内存的经历,或者被问到这样的问题——你的程序在运行时占用了多少内存(物理内存)?通常我们可以通过top命令查看进程占用了多少内存。这里我们可以看到VIRT、RES和SHR三个重要的指标,他们分别代表什么意思呢?这是本文需要跟大家一起探讨的问题。...

jvm疯狂吃内存,到底是谁的锅?

jvm应该是每一个java程序员都需要掌握的内容,但是在没有遇到问题之前,很多都是基于理论的,唯有实战才能增加个人的知识储备。本文是从一个角度来分析是谁在狂吃内存,希望对你有所帮助。本文是易观技术人员注意到一台开发机上各个微服务进程占用内存很高,随即便展开了调查......ps:本文来源于:http...

HTML5最新版本介绍

HTML5是HTML4.01和XHTML1.0之后超文本标记语言的最新版本,由一群自由思想者设计,最终实现了多媒体支持、交互性、更智能的表单和更好的语义标注。 HTML 5不只是 HTML规范的最新版本,它是用于生成现代 Web内容的一系列相关技术的总称,其中最重要的三个技术是:HTML5核心规范...

史上最全 vue-router 讲解 !!!

前端路由 前端路由是后来发展到SPA(单页应用)时才出现的概念。 SPA 就是一个WEB项目只有一个 HTML 页面,一旦页面加载完成,SPA 不会因为用户的操作而进行页面的重新加载或跳转。 前端路由在SPA项目中是必不可少的,页面的跳转、刷新都与路由有关,通过不同的url显示相应的页面。 优点:前...

Alpine.js 如何火起来的!比 React/Vue 如何?

大家好,很高兴又见面了,我是"高级前端?进阶?",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!前言前端 JavaScript 框架的创新是这个时代最伟大的技术文化现象之一。Alpine 发音为 /??lpa?n/,中文为阿尔卑斯山、...