CORS Spring Boot 2.1.2 不发送访问控制标头
Posted
技术标签:
【中文标题】CORS Spring Boot 2.1.2 不发送访问控制标头【英文标题】:CORS SpringBoot 2.1.2 Not Sending access control headers 【发布时间】:2021-12-18 21:49:42 【问题描述】:感谢您提供的任何帮助。
这看起来很简单,我以前做过,但是...到目前为止,我无法在我的请求响应中获取 CORS 访问控制标头。
我想使用全局配置选项,因为它允许使用方对其端点进行有限控制。 我尝试使用@CrossOrigin 注释进行调试,它似乎也没有返回标头。
我有两个控制器(还有更多,但它们不是我现在需要处理的)
-
具有 2 个 GET 端点的状态控制器
/健康
/健康检查
带有 1 个 POST 端点的上传控制器
/上传
我已经阅读了解决问题和正确实施 cors 的各种方法(我们没有使用 spring security)。除非跨源,否则代码可以正常编译和执行。具体来说,我们使用 swagger 来注释我们的代码,当我尝试使用 swagger 测试端点时,它会失败并出现一般的 CORS 错误。
使用 Postman 的 OPTIONS 请求返回:
Allow: POST, OPTIONS
但没有访问控制标头
所以进入代码:
CorsConfig.java
@Configuration
@EnableWebMvc
@PropertySource ("classpath:cors.properties")
@EnableConfigurationProperties (CorsProperties.class)
public class CorsConfig implements WebMvcConfigurer
private final CorsProperties corsProperties;
public CorsConfig(CorsProperties corsProperties)
this.corsProperties = corsProperties;
@Override
public void addCorsMappings(CorsRegistry registry)
for (CorsModel model : corsProperties.getModels())
for (String mapping : model.getEndpoints())
registry.addMapping(mapping)
.allowedMethods(removeInputQuotes(model.getAllowedMethods()))
.allowedHeaders(removeInputQuotes(model.getAllowedHeaders()))
.allowedOrigins(removeInputQuotes(model.getAllowedOrigins()))
.allowCredentials(false)
// this is a test, adding exposedHeaders did not seem to do anything
.exposedHeaders("Access-Control-Allow-Origin")
.maxAge(32600);
private String[] removeInputQuotes(List<String> input)
for (int i = 0; i < input.size(); i++)
input.set(i, input.get(i).replace("\"", "").replace("'", ""));
return input.toArray(new String[0]);
在调试上述内容时,一切似乎都被正确注入,例如所有变量都已设置。
CorsProperties.java
@ConfigurationProperties (prefix = "cors", ignoreUnknownFields = false)
public class CorsProperties
public List<CorsModel> models;
public List<CorsModel> getModels()
return models;
public void setModels(List<CorsModel> models)
this.models = models;
CorsModel.java
public class CorsModel
private List<String> endpoints;
private List<String> allowedOrigins;
private List<String> allowedHeaders;
private List<String> allowedMethods;
public List<String> getEndpoints()
return endpoints;
public void setEndpoints(List<String> endpoint)
this.endpoints = endpoint;
public List<String> getAllowedOrigins()
return allowedOrigins;
public void setAllowedOrigins(List<String> allowedOrigins)
this.allowedOrigins = allowedOrigins;
public List<String> getAllowedHeaders()
return allowedHeaders;
public void setAllowedHeaders(List<String> allowedHeaders)
this.allowedHeaders = allowedHeaders;
public List<String> getAllowedMethods()
return allowedMethods;
public void setAllowedMethods(List<String> allowedMethods)
this.allowedMethods = allowedMethods;
cors.properties
cors.models[0].allowed-headers=*
cors.models[0].allowed-methods=GET,POST,OPTIONS,HEAD
cors.models[0].allowed-origins=*
cors.models[0].endpoints[0]=/health
cors.models[0].endpoints[1]=/healthcheck
cors.models[0].endpoints[2]=/swagger**
cors.models[0].endpoints[3]=/upload
文件控制器.java
@RestController
public class FileController
@RequestMapping (path = "/upload", method = RequestMethod.POST,
produces = MediaType.APPLICATION_JSON_VALUE, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public ResponseEntity<?> upload(@RequestPart ("files")
List<MultipartFile> trackFiles)
// code to execute, this is an example, I cannot show the internals of this method
return new ResponseEntity<>(HttpStatus.OK);
StatusController.java
@RestController
public class StatusController
@GetMapping (value = "/health", produces=MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<HealthCheckResponse> health()
RuntimeMXBean rb = ManagementFactory.getRuntimeMXBean();
return new ResponseEntity<>(rb.getUptime(), HttpStatus.OK);
如果您已经走到了这一步,谢谢! 好吧,那部分我好像没看懂……
我想卷曲端点并在响应中查看访问控制标头
curl -I http://localhost:8080/health
curl -I http://localhost:8080/upload
etc...
卷曲响应:
HTTP/1.1 200
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
Date: Thu, 04 Nov 2021 16:40:48 GMT
据我所知,这是不正确的......它应该看起来像:
HTTP/1.1 200
Date: Thu, 04 Nov 2021 16:55:38 GMT
Content-Type: application/json;charset=UTF-8
Transfer-Encoding: chunked
access-control-allow-origin: *
access-control-allow-methods: *
我错过了什么?除了给玛丽打个招呼和注射弹簧安全剂,希望这会奏效。
【问题讨论】:
你在用springsecurity吗? 【参考方案1】:在这方面花了很多时间之后,我曾希望承认...我找到了一个解决方案,将 Cors 过滤合并到拦截器和过滤器中。
将此添加到配置 bean 将设置 cors,而无需在任何地方注入 MVC。
@Bean
@Order(1)
public CorsFilter corsFilter()
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
for (CorsModel model : corsProperties.getModels())
for (String mapping : model.getEndpoints())
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(removeInputQuotes(model.getAllowedOrigins()));
configuration.setAllowedMethods(removeInputQuotes(model.getAllowedMethods()));
configuration.setAllowedHeaders(removeInputQuotes(model.getAllowedHeaders()));
configuration.setAllowCredentials(true);
configuration.setMaxAge(32600L);
configuration.setExposedHeaders(Collections.singletonList("Authorization"));
source.registerCorsConfiguration(mapping, configuration);
return new CorsFilter(source);
我的主要 CorsConfig.java 类现在看起来像:
@Configuration
@PropertySource ("classpath:cors.properties")
@EnableConfigurationProperties (CorsProperties.class)
public class CorsConfig
private final CorsProperties corsProperties;
public CorsConfig(CorsProperties corsProperties)
this.corsProperties = corsProperties;
@Bean
@Order(1)
public CorsFilter corsFilter()
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
for (CorsModel model : corsProperties.getModels())
for (String mapping : model.getEndpoints())
final CorsConfiguration configuration = new CorsConfiguration();
configuration.setAllowedOrigins(removeInputQuotes(model.getAllowedOrigins()));
configuration.setAllowedMethods(removeInputQuotes(model.getAllowedMethods()));
configuration.setAllowedHeaders(removeInputQuotes(model.getAllowedHeaders()));
configuration.setAllowCredentials(true);
configuration.setMaxAge(32600L);
configuration.setExposedHeaders(Collections.singletonList("Authorization"));
source.registerCorsConfiguration(mapping, configuration);
return new CorsFilter(source);
private List<String> removeInputQuotes(List<String> input)
for (int i = 0; i < input.size(); i++)
input.set(i, input.get(i).replace("\"", "").replace("'", ""));
return input;
【讨论】:
以上是关于CORS Spring Boot 2.1.2 不发送访问控制标头的主要内容,如果未能解决你的问题,请参考以下文章