SpringBoot处理跨域请求(CORS)的五种方式

2025-05-14 10:30:37 156
魁首哥

一、cors基础概念

1. 什么是跨域请求?

当浏览器从一个域名的网页去请求另一个域名的资源时,如果域名、端口或协议不同,就会产生跨域请求。出于安全考虑,浏览器默认会阻止这类请求。

2. 简单请求 vs 预检请求

类型条件处理方式
简单请求get/head/post方法,且content-type为text/plain、multipart/form-data或application/x-www-form-urlencoded直接发送请求,带origin头
预检请求(options)不符合简单请求条件的其他请求先发送options请求,获得许可后再发送实际请求

二、spring boot处理cors的5种方式

1. 使用@crossorigin注解

适用场景:针对单个控制器或方法级别的cors配置

@restcontroller
@requestmapping("/api")
public class mycontroller {
    
    // 允许特定源的跨域访问
    @crossorigin(origins = "https://example.com")
    @getmapping("/resource")
    public responseentity getresource() {
        return responseentity.ok("跨域资源");
    }
    
    // 更详细的配置
    @crossorigin(origins = {"https://example.com", "https://api.example.com"},
                allowedheaders = {"content-type", "authorization"},
                methods = {requestmethod.get, requestmethod.post},
                maxage = 3600)
    @postmapping("/save")
    public responseentity saveresource() {
        return responseentity.ok("保存成功");
    }
}

2. 全局cors配置

适用场景:应用级别的统一cors配置

@configuration
public class webconfig implements webmvcconfigurer {
    
    @override
    public void addcorsmappings(corsregistry registry) {
        registry.addmapping("/api/**")  // 匹配的路径
                .allowedorigins("https://example.com", "https://api.example.com") // 允许的源
                .allowedmethods("get", "post", "put", "delete") // 允许的方法
                .allowedheaders("*") // 允许的请求头
                .exposedheaders("authorization", "content-disposition") // 暴露的响应头
                .allowcredentials(true) // 是否允许发送cookie
                .maxage(3600); // 预检请求缓存时间(秒)
        
        // 可以添加多个配置
        registry.addmapping("/public/**")
                .allowedorigins("*");
    }
}

3. 使用filter处理cors

适用场景:需要更底层控制或与非spring web环境集成

@configuration
public class corsfilterconfig {
    
    @bean
    public filterregistrationbean corsfilter() {
        urlbasedcorsconfigurationsource source = new urlbasedcorsconfigurationsource();
        corsconfiguration config = new corsconfiguration();
        
        // 配置cors规则
        config.setallowcredentials(true);
        config.addallowedorigin("https://example.com");
        config.addallowedheader("*");
        config.addallowedmethod("*");
        config.setmaxage(3600l);
        
        // 对所有路径生效
        source.registercorsconfiguration("/**", config);
        
        filterregistrationbean bean = 
            new filterregistrationbean<>(new corsfilter(source));
        bean.setorder(ordered.highest_precedence); // 设置最高优先级
        
        return bean;
    }
}

4. spring security中的cors配置

适用场景:使用spring security的项目

@configuration
@enablewebsecurity
public class securityconfig extends websecurityconfigureradapter {
    
    @override
    protected void configure(httpsecurity http) throws exception {
        http.cors().and() // 启用cors支持
            .csrf().disable() // 通常cors和csrf不能同时使用
            .authorizerequests()
            .antmatchers("/api/public/**").permitall()
            .anyrequest().authenticated();
    }
    
    // 提供cors配置源
    @bean
    corsconfigurationsource corsconfigurationsource() {
        corsconfiguration configuration = new corsconfiguration();
        configuration.setallowedorigins(arrays.aslist("https://example.com"));
        configuration.setallowedmethods(arrays.aslist("get", "post"));
        configuration.setallowedheaders(arrays.aslist("*"));
        
        urlbasedcorsconfigurationsource source = new urlbasedcorsconfigurationsource();
        source.registercorsconfiguration("/**", configuration);
        
        return source;
    }
}

5. 响应头手动设置

适用场景:需要动态控制cors头

@restcontroller
public class dynamiccorscontroller {
    
    @getmapping("/dynamic-cors")
    public responseentity dynamiccors(httpservletrequest request, 
                                           httpservletresponse response) {
        // 根据请求动态设置cors头
        string origin = request.getheader("origin");
        if (isallowedorigin(origin)) {
            response.setheader("access-control-allow-origin", origin);
            response.setheader("access-control-allow-credentials", "true");
            response.setheader("access-control-allow-methods", "get, post");
        }
        
        return responseentity.ok("动态cors响应");
    }
    
    private boolean isallowedorigin(string origin) {
        // 实现你的源验证逻辑
        return origin != null && origin.endswith("example.com");
    }
}

三、cors配置详解

1. 核心响应头说明

响应头说明
access-control-allow-origin允许访问的源,可以是具体域名或*(不推荐使用*,特别是需要凭证时)
access-control-allow-methods允许的http方法(get, post等)
access-control-allow-headers允许的请求头
access-control-expose-headers浏览器可以访问的响应头
access-control-allow-credentials是否允许发送cookie(true/false),设为true时allow-origin不能为*
access-control-max-age预检请求结果的缓存时间(秒)

2. 常见问题解决方案

问题1:预检请求(options)被拦截

解决方案

  • 确保options请求不被安全框架拦截
  • 在spring security中配置:
http.cors().and()
    .authorizerequests()
    .antmatchers(httpmethod.options, "/**").permitall()

问题2:带凭证的请求失败

解决方案

  • 确保allowcredentials(true)和具体的allowedorigins(不能是*)
  • 前端需要设置withcredentials: true(如axios)

问题3:特定响应头无法获取

解决方案

  • 使用exposedheaders暴露需要的头:
.exposedheaders("custom-header", "authorization")

四、最佳实践建议

  • 生产环境不要使用通配符*:明确指定允许的源
  • 合理限制http方法:只开放必要的方法(get/post等)
  • 考虑使用环境变量:动态配置允许的源
@value("${cors.allowed.origins}")
private string[] allowedorigins;

// 在配置中使用
.allowedorigins(allowedorigins)
  • 结合安全框架:spring security项目使用专门的cors配置
  • 测试不同场景:简单请求和预检请求都要测试

五、完整配置示例

@configuration
@enablewebmvc
public class corsconfig implements webmvcconfigurer {
    
    @value("${app.cors.allowed-origins}")
    private string[] allowedorigins;
    
    @override
    public void addcorsmappings(corsregistry registry) {
        registry.addmapping("/api/**")
                .allowedorigins(allowedorigins)
                .allowedmethods("get", "post", "put", "patch", "delete", "options")
                .allowedheaders("*")
                .exposedheaders("authorization", "content-disposition")
                .allowcredentials(true)
                .maxage(3600);
                
        registry.addmapping("/public/**")
                .allowedorigins("*")
                .allowedmethods("get", "options");
    }
    
    // 可选:提供cors过滤器作为备选
    @bean
    public filterregistrationbean corsfilter() {
        urlbasedcorsconfigurationsource source = new urlbasedcorsconfigurationsource();
        corsconfiguration config = new corsconfiguration();
        config.applypermitdefaultvalues();
        config.setallowcredentials(true);
        config.setallowedorigins(arrays.aslist(allowedorigins));
        source.registercorsconfiguration("/**", config);
        
        filterregistrationbean bean = new filterregistrationbean<>(new corsfilter(source));
        bean.setorder(ordered.highest_precedence);
        return bean;
    }
}

六、总结

spring boot提供了多种灵活的方式来处理cors:

  1. 简单场景:使用@crossorigin注解
  2. 统一配置:实现webmvcconfigureraddcorsmappings方法
  3. 底层控制:配置corsfilter
  4. 安全项目:结合spring security的cors()配置
  5. 动态需求:手动设置响应头

根据项目需求选择合适的方式,并遵循安全最佳实践,可以有效地解决跨域问题,同时保证应用的安全性。

以上就是springboot处理跨域请求(cors)的五种方式的详细内容,更多关于springboot处理跨域请求的资料请关注代码网其它相关文章!

分享
海报
156
上一篇:SpringBoot中配置Redis连接池的完整指南 下一篇:SpringBoot项目中使用Netty实现远程调用的示例代码

忘记密码?

图形验证码