欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot處理跨域請(qǐng)求(CORS)的五種方式

 更新時(shí)間:2025年04月20日 08:26:41   作者:北辰alk  
跨域資源共享(CORS)是現(xiàn)代Web開(kāi)發(fā)中常見(jiàn)的問(wèn)題,Spring?Boot提供了多種方式來(lái)處理CORS請(qǐng)求,下面我將詳細(xì)介紹各種實(shí)現(xiàn)方式及其適用場(chǎng)景,需要的朋友可以參考下

一、CORS基礎(chǔ)概念

1. 什么是跨域請(qǐng)求?

當(dāng)瀏覽器從一個(gè)域名的網(wǎng)頁(yè)去請(qǐng)求另一個(gè)域名的資源時(shí),如果域名、端口或協(xié)議不同,就會(huì)產(chǎn)生跨域請(qǐng)求。出于安全考慮,瀏覽器默認(rèn)會(huì)阻止這類(lèi)請(qǐng)求。

2. 簡(jiǎn)單請(qǐng)求 vs 預(yù)檢請(qǐng)求

類(lèi)型條件處理方式
簡(jiǎn)單請(qǐng)求GET/HEAD/POST方法,且Content-Type為text/plain、multipart/form-data或application/x-www-form-urlencoded直接發(fā)送請(qǐng)求,帶Origin頭
預(yù)檢請(qǐng)求(OPTIONS)不符合簡(jiǎn)單請(qǐng)求條件的其他請(qǐng)求先發(fā)送OPTIONS請(qǐng)求,獲得許可后再發(fā)送實(shí)際請(qǐng)求

二、Spring Boot處理CORS的5種方式

1. 使用@CrossOrigin注解

適用場(chǎng)景:針對(duì)單個(gè)控制器或方法級(jí)別的CORS配置

@RestController
@RequestMapping("/api")
public class MyController {
    
    // 允許特定源的跨域訪問(wèn)
    @CrossOrigin(origins = "https://example.com")
    @GetMapping("/resource")
    public ResponseEntity<String> getResource() {
        return ResponseEntity.ok("跨域資源");
    }
    
    // 更詳細(xì)的配置
    @CrossOrigin(origins = {"https://example.com", "https://api.example.com"},
                allowedHeaders = {"Content-Type", "Authorization"},
                methods = {RequestMethod.GET, RequestMethod.POST},
                maxAge = 3600)
    @PostMapping("/save")
    public ResponseEntity<String> saveResource() {
        return ResponseEntity.ok("保存成功");
    }
}

2. 全局CORS配置

適用場(chǎng)景:應(yīng)用級(jí)別的統(tǒng)一CORS配置

@Configuration
public class WebConfig implements WebMvcConfigurer {
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")  // 匹配的路徑
                .allowedOrigins("https://example.com", "https://api.example.com") // 允許的源
                .allowedMethods("GET", "POST", "PUT", "DELETE") // 允許的方法
                .allowedHeaders("*") // 允許的請(qǐng)求頭
                .exposedHeaders("Authorization", "Content-Disposition") // 暴露的響應(yīng)頭
                .allowCredentials(true) // 是否允許發(fā)送cookie
                .maxAge(3600); // 預(yù)檢請(qǐng)求緩存時(shí)間(秒)
        
        // 可以添加多個(gè)配置
        registry.addMapping("/public/**")
                .allowedOrigins("*");
    }
}

3. 使用Filter處理CORS

適用場(chǎng)景:需要更底層控制或與非Spring Web環(huán)境集成

@Configuration
public class CorsFilterConfig {
    
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        
        // 配置CORS規(guī)則
        config.setAllowCredentials(true);
        config.addAllowedOrigin("https://example.com");
        config.addAllowedHeader("*");
        config.addAllowedMethod("*");
        config.setMaxAge(3600L);
        
        // 對(duì)所有路徑生效
        source.registerCorsConfiguration("/**", config);
        
        FilterRegistrationBean<CorsFilter> bean = 
            new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE); // 設(shè)置最高優(yōu)先級(jí)
        
        return bean;
    }
}

4. Spring Security中的CORS配置

適用場(chǎng)景:使用Spring Security的項(xiàng)目

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().and() // 啟用CORS支持
            .csrf().disable() // 通常CORS和CSRF不能同時(shí)使用
            .authorizeRequests()
            .antMatchers("/api/public/**").permitAll()
            .anyRequest().authenticated();
    }
    
    // 提供CORS配置源
    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST"));
        configuration.setAllowedHeaders(Arrays.asList("*"));
        
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        
        return source;
    }
}

5. 響應(yīng)頭手動(dòng)設(shè)置

適用場(chǎng)景:需要?jiǎng)討B(tài)控制CORS頭

@RestController
public class DynamicCorsController {
    
    @GetMapping("/dynamic-cors")
    public ResponseEntity<String> dynamicCors(HttpServletRequest request, 
                                           HttpServletResponse response) {
        // 根據(jù)請(qǐng)求動(dòng)態(tài)設(shè)置CORS頭
        String origin = request.getHeader("Origin");
        if (isAllowedOrigin(origin)) {
            response.setHeader("Access-Control-Allow-Origin", origin);
            response.setHeader("Access-Control-Allow-Credentials", "true");
            response.setHeader("Access-Control-Allow-Methods", "GET, POST");
        }
        
        return ResponseEntity.ok("動(dòng)態(tài)CORS響應(yīng)");
    }
    
    private boolean isAllowedOrigin(String origin) {
        // 實(shí)現(xiàn)你的源驗(yàn)證邏輯
        return origin != null && origin.endsWith("example.com");
    }
}

三、CORS配置詳解

1. 核心響應(yīng)頭說(shuō)明

響應(yīng)頭說(shuō)明
Access-Control-Allow-Origin允許訪問(wèn)的源,可以是具體域名或*(不推薦使用*,特別是需要憑證時(shí))
Access-Control-Allow-Methods允許的HTTP方法(GET, POST等)
Access-Control-Allow-Headers允許的請(qǐng)求頭
Access-Control-Expose-Headers瀏覽器可以訪問(wèn)的響應(yīng)頭
Access-Control-Allow-Credentials是否允許發(fā)送cookie(true/false),設(shè)為true時(shí)Allow-Origin不能為*
Access-Control-Max-Age預(yù)檢請(qǐng)求結(jié)果的緩存時(shí)間(秒)

2. 常見(jiàn)問(wèn)題解決方案

問(wèn)題1:預(yù)檢請(qǐng)求(OPTIONS)被攔截

解決方案

  • 確保OPTIONS請(qǐng)求不被安全框架攔截
  • 在Spring Security中配置:
http.cors().and()
    .authorizeRequests()
    .antMatchers(HttpMethod.OPTIONS, "/**").permitAll()

問(wèn)題2:帶憑證的請(qǐng)求失敗

解決方案

  • 確保allowCredentials(true)和具體的allowedOrigins(不能是*)
  • 前端需要設(shè)置withCredentials: true(如axios)

問(wèn)題3:特定響應(yīng)頭無(wú)法獲取

解決方案

  • 使用exposedHeaders暴露需要的頭:
.exposedHeaders("Custom-Header", "Authorization")

四、最佳實(shí)踐建議

  • 生產(chǎn)環(huán)境不要使用通配符*:明確指定允許的源
  • 合理限制HTTP方法:只開(kāi)放必要的方法(GET/POST等)
  • 考慮使用環(huán)境變量:動(dòng)態(tài)配置允許的源
@Value("${cors.allowed.origins}")
private String[] allowedOrigins;

// 在配置中使用
.allowedOrigins(allowedOrigins)
  • 結(jié)合安全框架:Spring Security項(xiàng)目使用專(zhuān)門(mén)的CORS配置
  • 測(cè)試不同場(chǎng)景:簡(jiǎn)單請(qǐng)求和預(yù)檢請(qǐng)求都要測(cè)試

五、完整配置示例

@Configuration
@EnableWebMvc
public class CorsConfig implements WebMvcConfigurer {
    
    @Value("${app.cors.allowed-origins}")
    private String[] allowedOrigins;
    
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
                .allowedOrigins(allowedOrigins)
                .allowedMethods("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS")
                .allowedHeaders("*")
                .exposedHeaders("Authorization", "Content-Disposition")
                .allowCredentials(true)
                .maxAge(3600);
                
        registry.addMapping("/public/**")
                .allowedOrigins("*")
                .allowedMethods("GET", "OPTIONS");
    }
    
    // 可選:提供CORS過(guò)濾器作為備選
    @Bean
    public FilterRegistrationBean<CorsFilter> corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.applyPermitDefaultValues();
        config.setAllowCredentials(true);
        config.setAllowedOrigins(Arrays.asList(allowedOrigins));
        source.registerCorsConfiguration("/**", config);
        
        FilterRegistrationBean<CorsFilter> bean = new FilterRegistrationBean<>(new CorsFilter(source));
        bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
        return bean;
    }
}

六、總結(jié)

Spring Boot提供了多種靈活的方式來(lái)處理CORS:

  1. 簡(jiǎn)單場(chǎng)景:使用@CrossOrigin注解
  2. 統(tǒng)一配置:實(shí)現(xiàn)WebMvcConfigureraddCorsMappings方法
  3. 底層控制:配置CorsFilter
  4. 安全項(xiàng)目:結(jié)合Spring Security的cors()配置
  5. 動(dòng)態(tài)需求:手動(dòng)設(shè)置響應(yīng)頭

根據(jù)項(xiàng)目需求選擇合適的方式,并遵循安全最佳實(shí)踐,可以有效地解決跨域問(wèn)題,同時(shí)保證應(yīng)用的安全性。

以上就是SpringBoot處理跨域請(qǐng)求(CORS)的五種方式的詳細(xì)內(nèi)容,更多關(guān)于SpringBoot處理跨域請(qǐng)求的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • SpringBoot自定義注解如何解決公共字段填充問(wèn)題

    SpringBoot自定義注解如何解決公共字段填充問(wèn)題

    本文介紹了在系統(tǒng)開(kāi)發(fā)中,如何使用AOP切面編程實(shí)現(xiàn)公共字段自動(dòng)填充的功能,從而簡(jiǎn)化代碼,通過(guò)自定義注解和切面類(lèi),可以統(tǒng)一處理創(chuàng)建時(shí)間和修改時(shí)間,以及創(chuàng)建人和修改人的賦值操作
    2025-03-03
  • SpringMVC + servlet3.0 文件上傳的配置和實(shí)現(xiàn)代碼

    SpringMVC + servlet3.0 文件上傳的配置和實(shí)現(xiàn)代碼

    本篇文章主要介紹了SpringMVC + servlet3.0 文件上傳的配置和實(shí)現(xiàn)代碼,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下。
    2017-04-04
  • mybatis 如何利用resultMap復(fù)雜類(lèi)型list映射

    mybatis 如何利用resultMap復(fù)雜類(lèi)型list映射

    這篇文章主要介紹了mybatis 如何利用resultMap復(fù)雜類(lèi)型list映射的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • RocketMQ?NameServer架構(gòu)設(shè)計(jì)啟動(dòng)流程

    RocketMQ?NameServer架構(gòu)設(shè)計(jì)啟動(dòng)流程

    這篇文章主要為大家介紹了RocketMQ?NameServer架構(gòu)設(shè)計(jì)啟動(dòng)流程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-02-02
  • 關(guān)于Java中常見(jiàn)的負(fù)載均衡算法

    關(guān)于Java中常見(jiàn)的負(fù)載均衡算法

    這篇文章主要介紹了關(guān)于Java中常見(jiàn)的負(fù)載均衡算法,負(fù)載平衡是一種電子計(jì)算機(jī)技術(shù),用來(lái)在多個(gè)計(jì)算機(jī)、網(wǎng)絡(luò)連接、CPU、磁盤(pán)驅(qū)動(dòng)器或其他資源中分配負(fù)載,以達(dá)到優(yōu)化資源使用、最大化吞吐率、最小化響應(yīng)時(shí)間、同時(shí)避免過(guò)載的目的,需要的朋友可以參考下
    2023-08-08
  • Spring AI集成DeepSeek的詳細(xì)步驟

    Spring AI集成DeepSeek的詳細(xì)步驟

    DeepSeek 作為一款卓越的國(guó)產(chǎn) AI 模型,越來(lái)越多的公司考慮在自己的應(yīng)用中集成,對(duì)于 Java 應(yīng)用來(lái)說(shuō),我們可以借助 Spring AI 集成 DeepSeek,非常簡(jiǎn)單方便,本文給大家介紹了Spring AI集成DeepSeek的詳細(xì)步驟,需要的朋友可以參考下
    2025-02-02
  • java實(shí)現(xiàn)酷狗音樂(lè)臨時(shí)緩存文件轉(zhuǎn)換為MP3文件的方法

    java實(shí)現(xiàn)酷狗音樂(lè)臨時(shí)緩存文件轉(zhuǎn)換為MP3文件的方法

    這篇文章主要介紹了java實(shí)現(xiàn)酷狗音樂(lè)臨時(shí)緩存文件轉(zhuǎn)換為MP3文件的方法,涉及java針對(duì)文件操作的相關(guān)技巧,需要的朋友可以參考下
    2016-08-08
  • Java實(shí)現(xiàn)Jar文件的遍歷復(fù)制與文件追加

    Java實(shí)現(xiàn)Jar文件的遍歷復(fù)制與文件追加

    這篇文章主要為大家詳細(xì)介紹了如何利用Java實(shí)現(xiàn)Jar文件的遍歷復(fù)制與文件追加功能,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下
    2024-11-11
  • java實(shí)現(xiàn)簡(jiǎn)單銀行管理系統(tǒng)

    java實(shí)現(xiàn)簡(jiǎn)單銀行管理系統(tǒng)

    這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)簡(jiǎn)單銀行管理系統(tǒng),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-12-12
  • Java工程中可執(zhí)行JAR兩種打包方式詳解

    Java工程中可執(zhí)行JAR兩種打包方式詳解

    這篇文章主要為大家詳細(xì)介紹了Java工程中可執(zhí)行JAR兩種打包方式,一體化可執(zhí)行包和帶外部依賴(lài)lib的可執(zhí)行包,有需要的小伙伴可以學(xué)習(xí)一下
    2024-04-04

最新評(píng)論