在微服務架構中,前端與后端分離已經成為一種常見模式。這種模式下,前后端通常會部署在不同的域名或端口上,這就導致了跨域資源共享(CORS)問題。最近,在我們的項目中,我們遇到了這樣一個問題:“The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed”?
🛠? 問題描述
當瀏覽器發起一個跨域請求時,它首先會發送一個預檢請求(OPTIONS),以確定服務器是否允許該跨域請求。然而,在我們的案例中,出現了如下錯誤提示:?
The 'Access-Control-Allow-Origin' header contains multiple values '*, *', but only one is allowed
這意味著響應頭Access-Control-Allow-Origin
被設置了兩次,這通常是由于在多個地方配置了CORS支持,例如在每個微服務和網關中分別進行了配置,從而導致沖突。?
🔧 解決方案
為了解決上述問題,我們需要采取以下兩個步驟:
第一步:刪除注冊到Nacos中的服務中配置的CorsConfig
為了避免重復設置CORS頭信息,我們應該從各個微服務中移除任何現有的CORS配置。具體操作如下:
- 找到并刪除所有微服務中的
CorsConfig
類。 - 確保這些服務不再自動添加CORS相關的HTTP響應頭。
這樣做可以確保只有網關負責處理跨域請求,避免了多次設置相同響應頭的情況。?
第二步:在Gateway中配置跨域
接下來,在Spring Cloud Gateway中進行統一的CORS配置。這里提供了一個簡單的示例配置:
import org.springframework.context.annotation.Bean;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsWebFilter;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;public class CorsConfig {@Beanpublic CorsWebFilter corsFilter() {CorsConfiguration config = new CorsConfiguration();// 設置允許跨域訪問的源config.addAllowedOrigin("*");// 設置允許的方法config.addAllowedMethod("*");// 設置允許的頭信息config.addAllowedHeader("*");// 允許憑證config.setAllowCredentials(true);UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();source.registerCorsConfiguration("/**", config);return new CorsWebFilter(source);}
}
這段代碼創建了一個全局的CORS過濾器,適用于所有的路由。通過這種方式,我們可以確保每次跨域請求都被正確地處理,而不會出現重復的Access-Control-Allow-Origin
響應頭。?
路由規則配置解析
簡要解析Spring Cloud Gateway的路由規則定義,以及其如何工作。
- id: admin_routeuri: lb://mall-adminpredicates:- Path=/api/**filters:- RewritePath=/api/(?<segment>.*),/mall-admin/${segment}
通過這種配置方式,當客戶端發送請求到/api/users
時,Gateway首先檢查是否符合Path=/api/**
條件。如果符合條件,則應用RewritePath
過濾器將路徑轉換為/mall-admin/users
,然后根據負載均衡策略將請求轉發給mall-admin
服務的一個實例進行處理
結論
請注意,盡管上述配置使用了*
作為允許的源,但在生產環境中,出于安全考慮,應該明確指定具體的允許源,而不是使用通配符*
。此外,如果需要更復雜的CORS策略,如針對不同路徑應用不同的CORS規則,則可能需要進一步定制化配置。