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

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

ruisui882个月前 (03-07)技术分析11

京东大佬问我,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为什么会出现跨域问题?如何解决?” 的相关文章

Java教程:gitlab-使用入门

1 导读本教程主要讲解了GitLab在项目的环境搭建和基本的使用,可以帮助大家在企业中能够自主搭建GitLab服务,并且可以GitLab中的组、权限、项目自主操作GitLab简介GitLab环境搭建GitLab基本使用(组、权限、用户、项目)2 GitLab简介GitLab是整个DevOps生命周期...

身体越柔软越好?刻苦拉伸可能反而不健康 | 果断练

坐下伸直膝盖,双手用力向前伸,再用力……比昨天前进了一厘米,又进步了! 这么努力地拉伸,每个人都有自己的目标,也许是身体健康、线条柔美、放松肌肉、体测满分,也可能为了随时劈个叉,享受一片惊呼。 不过,身体柔软,可以享受到灵活的福利,也可能付出不稳定的代价,并不是越刻苦拉伸越好。太硬或者太软,都不安全...

vue v-html动态生成的html怎么加样式/事件

1、动态生成的html,样式不生效//html 布局 <view v-html="html"> {{html}} </view> //动态生成的元素 <view class="btngo" @tap="handleLink...

虚幻引擎5.5发布

IT之家 11 月 13 日消息,虚幻引擎 5.5 现已发布。据介绍,新版本虚幻引擎在动画创作、虚拟制作和移动游戏开发方面取得进步;渲染、摄像机内视觉特效和开发人员迭代等领域的部分功能已可用于生产。IT之家整理部分功能亮点如下:动画Sequencer增强虚幻引擎的非线性动画编辑器 Sequencer...

《暗黑破坏神 2:重制版》PC 版 2.3 版本发布,支持英伟达 DLSS

IT之家 12 月 3 日消息,暴雪为《暗黑破坏神 2:重制版》PC 版发布了更新 2.3 版本,添加了“离线难度缩放”滑块(玩家可以在单人游戏时增加挑战和奖励的级别)、多项辅助功能和用户界面改进,以及英伟达 DLSS 支持。玩法改进:玩家现在可以在离线游戏的选项菜单中使用“游戏难度等级”,它提供与...

Gemini应用在Android上广泛推出2.0闪电模式切换器

#头条精品计划# 快速导读谷歌(搜索)应用的测试频道在安卓设备的双子应用中推出了2.0闪电实验功能,现已向稳定用户开放。双子应用通过谷歌应用运行,目前推出的15.50版本中,用户可通过模型选择器体验不同选项,包括1.5专业版、1.5闪电版和2.0闪电实验版。2.0闪电实验模型提供了更快的响应速度和优...