Spring Authorization Server跨域问题:CORS阻止XMLHttpRequest访问
搭建了基于Spring Boot的基础Spring Authorization Server,尝试通过使用angular-auth-oidc-client的Angular应用访问该服务,登录时出现如下CORS错误:
Access to XMLHttpRequest at 'http://localhost:9000/mydomain/.well-known/openid-configuration' from origin 'http://localhost:4200' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
多次尝试修复未成功,授权服务器相关配置代码如下:
// @formatter:off @Bean public RegisteredClientRepository registeredClientRepository() { // removed } // @formatter:on @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(Arrays.asList("*")); config.setAllowedMethods(Arrays.asList("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH")); config.setAllowedHeaders(Arrays.asList("*")); config.setAllowCredentials(true); config.addAllowedOrigin("*"); config.addAllowedHeader("*"); config.addAllowedMethod("GET"); config.addAllowedMethod("POST"); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } // @formatter:off @Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); http .formLogin(Customizer.withDefaults()) .cors().configurationSource(corsConfigurationSource()); return http.build(); } // @formatter:on
补充说明:已在application.yml中配置端口和上下文路径:
server: port: 9000 servlet: context-path: /mydomain
该CORS配置看似完全开放,但问题仍存在,请问是否有未注意到的错误?
你的CORS配置存在两个关键问题:
setAllowCredentials(true)与通配符*冲突
当开启allowCredentials时,CORS规范明确禁止allowedOrigins使用通配符*,必须指定具体的允许来源(比如你的Angular应用地址http://localhost:4200)。浏览器会直接忽略这种冲突配置,导致CORS响应头无法正确返回。CORS配置的优先级与加载顺序问题
OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http)会注册自身的过滤器链,你的CORS配置可能未被正确应用到OIDC元数据端点(.well-known/openid-configuration)上,需要确保CORS过滤器在Spring Security过滤器之前执行。
修复步骤:
步骤1:修正CORS配置,替换通配符为具体来源
修改corsConfigurationSource方法,移除冗余配置并指定允许的Origin:
@Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); // 替换为你的Angular应用实际地址,禁用通配符 config.setAllowedOrigins(Arrays.asList("http://localhost:4200")); config.setAllowedMethods(Arrays.asList("HEAD", "GET", "PUT", "POST", "DELETE", "PATCH")); config.setAllowedHeaders(Arrays.asList("*")); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; }
步骤2:调整SecurityFilterChain的配置顺序
确保CORS配置先于其他Spring Security规则生效,修改authServerSecurityFilterChain方法:
@Bean @Order(Ordered.HIGHEST_PRECEDENCE) public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); // 先配置CORS,再添加其他安全规则 http .cors(cors -> cors.configurationSource(corsConfigurationSource())) .formLogin(Customizer.withDefaults()); return http.build(); }
完成以上修改后,重启授权服务器,再次测试Angular应用的登录流程,CORS错误即可解决。
内容的提问来源于stack exchange,提问作者Jason

