簡體   English   中英

CORS SpringBoot 2.1.2 不發送訪問控制標頭

[英]CORS SpringBoot 2.1.2 Not Sending access control headers

感謝您提供的任何幫助。

這看起來很簡單,我以前做過,但是......到目前為止,我無法在我的請求響應中獲得 CORS 訪問控制標頭。

我想使用全局配置選項,因為它允許對使用方的端點進行有限控制。 我曾嘗試使用 @CrossOrigin 注釋進行調試,但它似乎也沒有返回標頭。

我有兩個控制器(還有更多,但它們不是我現在需要處理的)

  1. 具有 2 個 GET 端點的狀態控制器
    • /健康
    • /健康檢查
  2. 具有 1 個 POST 端點的上傳控制器
    • /上傳

我已經閱讀了解決問題並正確實施 cors 的各種方法(我們沒有使用 spring 安全性)。 除非跨原點,否則代碼編譯並執行得很好。 具體來說,我們使用 swagger 來注釋我們的代碼,當我嘗試使用 swagger 來測試端點時,它會因通用 CORS 錯誤而失敗。

使用 Postman 的 OPTIONS 請求返回:

Allow: POST, OPTIONS

但沒有訪問控制頭

所以進入代碼:

配置文件

@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

文件控制器

@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);
    }
}

狀態控制器.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: *

我錯過了什么? 除了接受冰雹瑪麗和注入春季安全希望這會奏效。

在花了很多很多時間之后,我曾經希望承認......我找到了一個將 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;
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM