You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

本地React应用无法请求AWS EC2上的Spring Boot后端(CORS错误)

Spring Boot部署AWS EC2后CORS错误解决

背景

我开发了一个后端基于Spring Boot、前端基于React的应用,本地同时运行时功能完全正常。

问题

将后端部署到AWS EC2实例后,前端发起请求时出现CORS错误。
CORS错误截图
以下是本地运行时有效的Spring CORS配置:

安全配置类

@Configuration
public class Config {
    /**
     * 创建密码编码器Bean,用于后续在数据库中加密存储密码
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration builder) throws Exception {
        return builder.getAuthenticationManager();
    }

    @Bean
    public CorsFilter corsFilter() {
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowCredentials(true);
        corsConfiguration.setAllowedOrigins(Constants.CORS_ALLOWED_ORIGINS);
        corsConfiguration.setAllowedHeaders(Constants.CORS_ALLOWED_HEADERS);
        corsConfiguration.setExposedHeaders(Constants.CORS_EXPOSED_HEADERS);
        corsConfiguration.setAllowedMethods(Constants.CORS_ALLOWED_METHODS);
        UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();
        urlBasedCorsConfigurationSource.registerCorsConfiguration(Constants.CORS_CONFIGURATION_PATTERN, corsConfiguration);
        return new CorsFilter(urlBasedCorsConfigurationSource);
    }
}

常量类

public class Constants {
    public static final String RESIDENT_NID_FRONT_IMAGE_URL = "/images/residents/nid/";
    public static final String RESIDENT_NID_BACK_IMAGE_URL = "/images/residents/nid/";
    public static final String UPLOADED_FOLDER_GUEST_IMAGE = "/images/guests/profile/";

    public static final Integer STATUS_SUCCESS = HttpStatus.OK.value();
    public static final Integer STATUS_BAD_REQUEST = HttpStatus.BAD_REQUEST.value();
    public static final Integer STATUS_NOT_FOUND = HttpStatus.NOT_FOUND.value();
    public static final Integer STATUS_SERVER_ERROR = HttpStatus.INTERNAL_SERVER_ERROR.value();
    public static final Integer STATUS_UNAUTHORIZED = HttpStatus.UNAUTHORIZED.value();
    public static final String UPLOADED_FOLDER_GUEST_DOC_IMAGE = "/images/guests/doc/" ;
    public static final String RESIDENT_IMAGE_URL = "/images/residents/profile/";
    public static final String FRONT = "FRONT";
    public static final String BACK = "BACK";
    public static final String SECRET = "SecretKeyToGenJWTs";
    public static final long EXPIRATION_TIME = 864_000_000; // 10天
    public static final String TOKEN_PREFIX = "Bearer ";
    public static final String HEADER_STRING = "Authorization";
    public static final String PRIVILEGES = "privileges";
    public static final String ID = "id";
    public static final String AUTHORIZATION = "Authorization";
    public static final String BEARER = "Bearer ";

    public static final List<String> CORS_ALLOWED_ORIGINS = List.of("http://127.0.0.1:3000", "http://localhost:3000", "*");
    public static final List<String> CORS_ALLOWED_HEADERS = Arrays.asList(
            "Origin", "Access-Control-Allow-Origin", "Content-Type",
            "Accept", "Authorization", "Origin, Accept", "X-Requested-With",
            "Access-Control-Request-Method", "Access-Control-Request-Headers");
    public static final List<String> CORS_EXPOSED_HEADERS =Arrays.asList(
            "Origin", "Content-Type", "Accept", "Authorization",
            "Access-Control-Allow-Origin", "Access-Control-Allow-Origin", "Access-Control-Allow-Credentials");
    public static final List<String> CORS_ALLOWED_METHODS =Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS", "PATCH", "OPTIONS");
    public static final String CORS_CONFIGURATION_PATTERN = "/**";

    public static final String [] AUTH_WHITELIST = {
            "/authentication/web/login",
            "/authentication/web/signup"
    };

    public static String generateOtp(){
        String numbers = "0123456789";

        Random rndm_method = new Random();

        char[] otp = new char[4];

        for (int i = 0; i < 4; i++)
        {
            // 使用charAt()获取字符值,nextInt()生成随机索引
            otp[i] =
                    numbers.charAt(rndm_method.nextInt(numbers.length()));
        }

        return Arrays.toString(otp);
    }
}

补充说明

  • 使用Postman发送请求可正常工作
  • 若此问题重复,请勿介意

问题分析与解决步骤

1. 修正CORS源配置冲突

当setAllowCredentials(true)时,浏览器不允许使用*作为允许源,必须指定具体的前端线上域名(比如https://your-frontend-domain.com)。修改Constants类中的CORS_ALLOWED_ORIGINS,替换*为实际前端地址,或通过环境变量动态配置:

// 示例:替换为线上前端地址
public static final List<String> CORS_ALLOWED_ORIGINS = List.of(
    "http://127.0.0.1:3000", 
    "http://localhost:3000", 
    "https://your-production-frontend.com"
);

2. 确保CORS过滤器优先级高于Spring Security

如果项目使用Spring Security,需保证CORS过滤器在Security拦截器前执行。在Security配置类中添加如下配置:

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private CorsFilter corsFilter;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 先添加CORS过滤器
        http.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class);
        http.cors().and()
            .csrf().disable()
            // 其他安全配置...
    }
}

3. 检查EC2安全组配置

  • 确保EC2安全组允许前端域名/IP的入站请求,开放后端服务端口(如8080)
  • 确认安全组允许OPTIONS方法(CORS预检请求依赖该方法)

4. 负载均衡/反向代理配置检查

若使用AWS ALB(应用负载均衡):

  • 确保负载均衡监听器转发CORS相关请求头
  • 在负载均衡中配置正确的源允许规则,避免覆盖后端CORS配置

内容的提问来源于stack exchange,提问作者Adil Mir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 15:45:20