知識庫 / Spring RSS 訂閱

Spring 中跨域資源共享 (CORS)

Spring
HongKong
4
02:40 PM · Dec 06 ,2025

1. 概述

在任何現代瀏覽器中,跨源資源共享 (CORS) 規範與 HTML5 和通過 REST API 消費數據的 JS 客户端的出現而相關。

通常,提供 JS 的主機(例如 example.com)與提供數據的主機(例如 api.example.com)不同。在這種情況下,CORS 允許跨域通信。

Spring 提供了對 CORS 的一流 支持,提供了一種簡單而強大的配置方法,可用於在任何 Spring 或 Spring Boot Web 應用程序中配置 CORS。

2. 控制器方法 CORS 配置

啓用 CORS 非常簡單 — 只需要添加註解

我們可以用多種不同的方式來實現它。

2.1. 在帶有 <em @RequestMapping- 註解的 Handler 方法上使用 <em @CrossOrigin

@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin
    @RequestMapping(method = RequestMethod.GET, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

在上面的示例中,我們僅啓用了 CORS 對於 retrieve() 方法。我們可以看到,我們沒有為 @CrossOrigin 註解設置任何配置,因此它使用了默認值:

  • 所有來源均被允許。
  • 允許的 HTTP 方法是 @RequestMapping 註解中指定的(GET,在本示例中)。
  • 預檢響應緩存的時間(maxAge)為 30 分鐘。

2.2. 在控制器上使用 <em @CrossOrigin

@CrossOrigin(origins = "http://example.com", maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @RequestMapping(method = RequestMethod.GET, path = "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

本次,我們已在類級別添加了 @CrossOrigin 註解。因此,retrieve()remove() 方法均已啓用。可以通過指定註解屬性的值(例如 originsmethodsallowedHeadersexposedHeadersallowCredentialsmaxAge)來自定義配置。

2.3. @CrossOrigin on Controller and Handler Method

@CrossOrigin(maxAge = 3600)
@RestController
@RequestMapping("/account")
public class AccountController {

    @CrossOrigin("http://example.com")
    @RequestMapping(method = RequestMethod.GET, "/{id}")
    public Account retrieve(@PathVariable Long id) {
        // ...
    }

    @RequestMapping(method = RequestMethod.DELETE, path = "/{id}")
    public void remove(@PathVariable Long id) {
        // ...
    }
}

Spring 將會結合兩個註解的屬性以創建合併的 CORS 配置。

在這裏,兩個方法都將具有 3,600 秒的 maxAgeremove() 方法允許所有來源,而retrieve() 方法僅允許來自 http://example.com 的來源。

3. 全局 CORS 配置

作為一種替代方案,Spring 允許我們通過控制器定義全局 CORS 配置。這類似於使用基於 Filter 的解決方案,但可以在 Spring MVC 中聲明,並與精細的 @CrossOrigin 配置結合使用。

默認情況下,允許所有源頭和 GET、HEAD 和 POST 方法。

3.1. JavaConfig

@Configuration
@EnableWebMvc
public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**");
    }
}

上述示例允許從任何源頭嚮應用程序中的任何端點發起 CORS 請求。

為了進一步限制,registry.addMapping 方法返回一個 CorsRegistration 對象,我們可以利用它進行額外的配置。 此外,還有一個 allowedOrigins 方法,允許我們指定允許的源列表。 這在我們需要在運行時從外部源加載此數組時非常有用。

此外,還有 allowedMethodsallowedHeadersexposedHeadersmaxAgeallowCredentials 等方法,可用於設置響應頭和自定義選項。 例如,我們可以通過將 allowedMethods(“*”) 添加到上述配置中,來允許任何 HTTP 方法通過 CORS。

值得注意的是,自 2.4.0 版本以來,Spring Boot 引入了 allowedOriginPatterns,除了 allowedOrigins,提供了更大的靈活性。 此外,當 allowCredentials 為 true 時,allowedOrigins 不能包含特殊值 ‘*’,因為這無法設置在 Access-Control-Allow-Origin 響應頭中。 為了解決此問題並允許憑據設置為一組源,我們可以顯式列出它們,或者考慮使用 allowedOriginPatterns

3.2. XML 命名空間

這段最小的 XML 配置允許在 路徑模式上啓用 CORS,並具有與 JavaConfig 一樣默認的屬性:

<mvc:cors>
    <mvc:mapping path="/**" />
</mvc:cors>

當然,以下是翻譯後的內容:

還可以聲明多個 CORS 映射,並自定義其屬性:

<mvc:cors>

    <mvc:mapping path="/api/**"
        allowed-origins="http://domain1.com, http://domain2.com"
        allowed-methods="GET, PUT"
        allowed-headers="header1, header2, header3"
        exposed-headers="header1, header2" allow-credentials="false"
        max-age="123" />

    <mvc:mapping path="/resources/**"
        allowed-origins="http://domain1.com" />

</mvc:cors>

4. 使用 Spring Security 進行 CORS 處理

如果我們在項目中使用了 Spring Security,則必須採取額外的步驟以確保其與 CORS 兼容。這是因為 CORS 需要在先進行處理。否則,Spring Security 會在請求到達 Spring MVC 之前拒絕該請求。

幸運的是,Spring Security 提供了內置解決方案:

@EnableWebSecurity
public class WebSecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors().and()...
    }
}

本文檔將更詳細地解釋相關內容。

我們可以配置 CORS 以覆蓋默認的 Spring Security CORS 處理。為此,我們需要添加一個 CorsConfigurationSource Bean,該 Bean 使用 CorsConfiguration 實例來處理 CORS 配置。 http.cors() 方法如果添加了 corsFilter Bean,則使用 CorsFilter,否則使用 CorsConfigurationSource。如果兩者都沒有配置,則使用 Spring MVC 模式檢查器處理程序。

讓我們在 WebSecurityConfig 類中添加 CorsConfigurationSource Bean:

@Bean
CorsConfigurationSource corsConfigurationSource() {
    CorsConfiguration configuration = new CorsConfiguration();
    configuration.setAllowedOrigins(Arrays.asList("*"));
    configuration.setAllowedMethods(Arrays.asList("*"));
    configuration.setAllowedHeaders(Arrays.asList("*"));
    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", configuration);
    return source;
}

在這裏,我們使用默認構造函數創建一個 CorsConfiguration 實例,然後設置允許的 origin、允許的方法和響應頭。上述配置允許來自任何 origin、任何方法和任何頭部的請求到達應用程序中的任何 endpoint。最後,我們將它作為參數傳遞給 UrlBasedCorsConfigurationSource 實例,並返回它。

5. 工作原理

CORS 請求會自動分發到註冊的 HandlerMappings

它們處理 CORS 預檢請求並使用 CorsProcessor 實現(默認情況下是 DefaultCorsProcessor)來添加相關的 CORS 響應頭(例如 Access-Control-Allow-Origin)。

CorsConfiguration 允許我們指定 CORS 請求的處理方式,包括允許的源、頭和方法等。我們可以通過多種方式提供它:

  • AbstractHandlerMapping#setCorsConfiguration() 允許我們指定一個 Map,其中包含多個 CorsConfiguration,並映射到路徑模式,例如 /api/**
  • 子類可以通過重寫 AbstractHandlerMapping#getCorsConfiguration(Object, HttpServletRequest) 方法提供自己的 CorsConfiguration
  • 處理器可以實現 CorsConfigurationSource 接口(例如 ResourceHttpRequestHandler 現在正在執行此操作)以為每個請求提供 CorsConfiguration

6. 結論

在本文中,我們展示了 Spring 如何提供支持,以便在我們的應用程序中啓用 CORS。

我們首先從控制器配置開始。我們瞭解到,只需在特定方法或整個控制器中添加註解 @CrossOrigin 即可啓用 CORS。

此外,我們還了解到,為了在控制器之外控制 CORS 配置,可以使用 JavaConfig 或 XML 文件進行平滑配置。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.