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

SpringBoot+Vue跨域配置(CORS)問題得解決過程

 更新時間:2024年08月14日 08:57:33   作者:繁依Fanyi  
在使用 Spring Boot 和 Vue 開發(fā)前后端分離的項目時,跨域資源共享(CORS)問題是一個常見的挑戰(zhàn),接下來,我將分享我是如何一步步解決這個問題的,包括中間的一些試錯過程,希望能夠幫助到正在經(jīng)歷類似問題的你

1. 問題描述

在我們開發(fā)的過程中,Vue 前端需要與 Spring Boot 后端通信。如果后端沒有正確配置 CORS,瀏覽器會進行跨域檢查并阻止請求,報錯信息如下:

Access to XMLHttpRequest at 'http://localhost:8789/auth/register' from origin 'http://localhost:8081' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

2. 解決方案概述

為了解決這個問題,我們需要在 Spring Boot 應用中配置 CORS。這個過程包括創(chuàng)建一個 CORS 配置類,并在 Spring Security 配置類中應用這個配置。

3. 試錯過程

3.1 初步嘗試:簡單的 CORS 配置

我首先嘗試在 Spring Boot 中添加一個簡單的 CORS 配置類:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
public class CorsConfig {

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("*");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");
        configuration.setAllowCredentials(true);
        configuration.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

然后,在 WebSecurityConfig 中應用這個配置:

http.cors().configurationSource(corsConfigurationSource());

結(jié)果,前端依舊報錯,沒有任何變化。

3.2 細化 Security 配置

我接著嘗試在 WebSecurityConfig 中進一步細化 CORS 配置:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.cors().configurationSource(corsConfigurationSource())
            .and().csrf().disable();
    }

    @Bean
    CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.addAllowedOrigin("*");
        configuration.addAllowedMethod("*");
        configuration.addAllowedHeader("*");
        configuration.setAllowCredentials(true);
        configuration.setMaxAge(3600L);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
}

然而,前端還是無法正常發(fā)起跨域請求,這讓我非常困惑。

3.3 嘗試代理配置

為了確保開發(fā)過程中跨域請求能正確代理到后端,我在 Vue 項目中添加了代理配置:

首先,確保項目使用 vue-cli 創(chuàng)建,并確保有 vue.config.js 文件。然后添加如下代理配置:

let proxyObj = {};
proxyObj['/'] = {
    target: 'http://localhost:8789/',
    changeOrigin: true,
    pathRewrite: {
        '^/': ''
    }
}

module.exports = {
    devServer: {
        open: true,
        host: 'localhost',
        port: 8081,
        proxy: proxyObj,
    },
}

這種配置可以使前端的跨域請求通過代理轉(zhuǎn)發(fā)到后端。不過,這只是開發(fā)環(huán)境下的解決方案,并沒有真正解決后端的 CORS 配置問題。

3.4 最終解決方案:完善的 CORS 和 Security 配置

經(jīng)過幾次嘗試和查閱資料后,我最終找到了一個有效的解決方案,結(jié)合之前的經(jīng)驗,創(chuàng)建了一個完善的 CORS 和 Security 配置。

CorsConfig.java

package cn.techfanyi.fanyi.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
public class CorsConfig {

    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration corsConfig = new CorsConfiguration();
        corsConfig.addAllowedOriginPattern("*"); // 允許任何源
        corsConfig.addAllowedMethod("*"); // 允許任何HTTP方法
        corsConfig.addAllowedHeader("*"); // 允許任何HTTP頭
        corsConfig.setAllowCredentials(true); // 允許證書(cookies)
        corsConfig.setMaxAge(3600L); // 預檢請求的緩存時間(秒)

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", corsConfig); // 對所有路徑應用這個配置
        return source;
    }
}

WebSecurityConfig.java

package cn.techfanyi.fanyi.config;

import cn.techfanyi.fanyi.filter.JwtRequestFilter;
import cn.techfanyi.fanyi.security.CustomAccessDeniedHandler;
import cn.techfanyi.fanyi.security.CustomAuthenticationEntryPoint;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig {

    private final JwtRequestFilter jwtRequestFilter;
    private final CustomAuthenticationEntryPoint customAuthenticationEntryPoint;
    private final CustomAccessDeniedHandler customAccessDeniedHandler;

    public WebSecurityConfig(JwtRequestFilter jwtRequestFilter,
                          CustomAuthenticationEntryPoint customAuthenticationEntryPoint,
                          CustomAccessDeniedHandler customAccessDeniedHandler) {
        this.jwtRequestFilter = jwtRequestFilter;
        this.customAuthenticationEntryPoint = customAuthenticationEntryPoint;
        this.customAccessDeniedHandler = customAccessDeniedHandler;
    }

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws  Exception {
        http.csrf().disable()
                .cors(cors -> cors.configurationSource(corsConfigurationSource()))
                .authorizeRequests(authorizedRequests ->
                        authorizedRequests.requestMatchers("/**").permitAll()
                                .anyRequest().authenticated())
                .exceptionHandling(exceptionHandling ->
                        exceptionHandling.authenticationEntryPoint(customAuthenticationEntryPoint)
                                .accessDeniedHandler(customAccessDeniedHandler))
                .sessionManagement(sessionManagement ->
                        sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
                .addFilterBefore(jwtRequestFilter, UsernamePasswordAuthenticationFilter.class);

        return http.build();
    }

    @Bean
    public BCryptPasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }

    private CorsConfigurationSource corsConfigurationSource() {
        return new CorsConfig().corsConfigurationSource();
    }
}

但是又出現(xiàn)以下錯誤:

java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.

這個錯誤信息表明,在 Spring Boot 的 CORS 配置中,當 allowCredentials 設置為 true 時,allowedOrigins 不能包含特殊值 "*", 因為瀏覽器不允許在 Access-Control-Allow-Origin 響應頭中設置 "*", 同時還允許憑證(如 cookies)。此時應該使用 allowedOriginPatterns 來代替 allowedOrigins。

具體的錯誤原因如下:

java.lang.IllegalArgumentException: When allowCredentials is true, allowedOrigins cannot contain the special value "*" since that cannot be set on the "Access-Control-Allow-Origin" response header. To allow credentials to a set of origins, list them explicitly or consider using "allowedOriginPatterns" instead.

這意味著當 allowCredentials 設置為 true 時,不能將 allowedOrigins 設置為 "*", 因為它不能在響應頭中設置 Access-Control-Allow-Origin 為 "*", 同時還允許憑證。為了解決這個問題,您需要將 allowedOrigins 改為使用 allowedOriginPatterns。

修改 CorsConfigurationSource 如下:

 @Bean
 public CorsConfigurationSource corsConfigurationSource() {
     CorsConfiguration corsConfig = new CorsConfiguration();
     corsConfig.addAllowedOriginPattern("*"); // 使用 allowedOriginPatterns 代替 allowedOrigins
     corsConfig.addAllowedMethod("*"); 
     corsConfig.addAllowedHeader("*");
     corsConfig.setAllowCredentials(true);
     corsConfig.setMaxAge(3600L);

     UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
     source.registerCorsConfiguration("/**", corsConfig);
     return source;
 }

通過以上配置,可以解決 allowCredentials 和 allowedOrigins 中 "*" 沖突的問題,使得您的 Spring Boot 應用可以正確處理跨域請求。

通過以上配置,前端請求終于可以成功與后端通信,CORS 問題不再出現(xiàn)。

4. 為什么要這樣修改

在 Spring Security 6 中,安全配置的方式有所變化。與之前版本相比,Spring Security 6 更加靈活和模塊化。為了使 CORS 配置生效,我們需要:

  1. 明確指定 CORS 配置源:在 securityFilterChain 方法中,通過 http.cors(cors -> cors.configurationSource(corsConfigurationSource())) 明確指定使用我們自定義的 CorsConfigurationSource。
  2. 禁用默認的 CSRF 保護:對于大多數(shù) API 項目,特別是無狀態(tài)的 RESTful 服務,禁用 CSRF 是常見的做法。通過 http.csrf().disable() 來實現(xiàn)。
  3. 配置異常處理和會話管理:確保我們的應用是無狀態(tài)的,并且正確處理認證和授權(quán)異常。

5. 結(jié)果

經(jīng)過這些配置,前端可以順利地與后端通信,避免了 CORS 錯誤。整個過程讓我對 CORS 配置有了更深入的理解。

以上就是SpringBoot+Vue跨域配置(CORS)問題得解決過程的詳細內(nèi)容,更多關(guān)于SpringBoot Vue跨域配置解決的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • java FileWriter 追加文件及文件改名方式

    java FileWriter 追加文件及文件改名方式

    這篇文章主要介紹了java FileWriter 追加文件及文件改名的操作,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-07-07
  • spring?參數(shù)校驗Validation示例詳解

    spring?參數(shù)校驗Validation示例詳解

    Spring提供了Validation工具類來實現(xiàn)對客戶端傳來的請求參數(shù)的有效校驗,本文給大家介紹spring?參數(shù)校驗Validation示例詳解,感興趣的朋友一起看看吧
    2024-12-12
  • 推薦幾款非常實用的IDEA插件小結(jié)

    推薦幾款非常實用的IDEA插件小結(jié)

    這篇文章主要介紹了推薦幾款非常實用的IDEA插件小結(jié),解決你開發(fā)中可望而又不好找的插件,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2019-01-01
  • 詳解五種方式讓你在java中讀取properties文件內(nèi)容不再是難題

    詳解五種方式讓你在java中讀取properties文件內(nèi)容不再是難題

    這篇文章主要介紹了詳解五種方式讓你在java中讀取properties文件內(nèi)容不再是難題 ,非常具有實用價值,需要的朋友可以參考下。
    2016-12-12
  • Spring?boot?easyexcel?實現(xiàn)復合數(shù)據(jù)導出、按模塊導出功能

    Spring?boot?easyexcel?實現(xiàn)復合數(shù)據(jù)導出、按模塊導出功能

    這篇文章主要介紹了Spring?boot?easyexcel?實現(xiàn)復合數(shù)據(jù)導出、按模塊導出,實現(xiàn)思路流程是準備一個導出基礎填充模板,默認填充key,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2023-09-09
  • Java SerialVersionUID作用詳解

    Java SerialVersionUID作用詳解

    這篇文章主要介紹了Java SerialVersionUID作用詳解,本篇文章通過簡要的案例,講解了該項技術(shù)的了解與使用,以下就是詳細內(nèi)容,需要的朋友可以參考下
    2021-08-08
  • Java8語法糖之Lambda表達式的深入講解

    Java8語法糖之Lambda表達式的深入講解

    這篇文章主要給大家介紹了關(guān)于Java8語法糖之Lambda表達式的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-02-02
  • Springboot?jpa使用sum()函數(shù)返回結(jié)果如何被接收

    Springboot?jpa使用sum()函數(shù)返回結(jié)果如何被接收

    這篇文章主要介紹了Springboot?jpa使用sum()函數(shù)返回結(jié)果如何接收,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-02-02
  • Java詳細講解不同版本的接口語法和抽象類與接口的區(qū)別

    Java詳細講解不同版本的接口語法和抽象類與接口的區(qū)別

    對于面向?qū)ο缶幊虂碚f,抽象是它的一大特征之一,在?Java?中可以通過兩種形式來體現(xiàn)OOP的抽象:接口和抽象類,下面這篇文章主要給大家介紹了關(guān)于Java入門基礎之抽象類與接口的相關(guān)資料,需要的朋友可以參考下
    2022-04-04
  • Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學習使用Java,感興趣的朋友可以了解下
    2021-03-03

最新評論