CORS

Posted by Adam on August 24, 2022
# 🌐 CORS 統整(以 Spring Boot 為例) --- ## 🧠 什麼是 CORS? **CORS(Cross-Origin Resource Sharing)** 是瀏覽器用來保護使用者資料的一種安全機制,**限制不同網域之間的 HTTP 請求行為**。 --- ## 🧭 何謂「跨來源」? 來源 = 協定(protocol)+ 網域(domain)+ 埠號(port) 只要其中一項不同,就視為跨來源(cross-origin)請求。 例如: * `https://api.example.com` vs. `https://www.example.com` → 跨來源(不同子網域) * `http://example.com` vs. `https://example.com` → 跨來源(不同協定) * `https://example.com:8080` vs. `https://example.com:443` → 跨來源(不同 port) --- ## ⚠️ 為何需要設定 CORS? 預設下,瀏覽器會阻止網頁向不同來源發出請求。 若後端未正確回應 CORS headers,則瀏覽器會擋下回應,即使伺服器處理成功,前端仍會顯示錯誤。 --- ## ✅ Spring Boot 實作方式 ### ✅ 1. 全域 CORS 設定(推薦) 在 `WebMvcConfigurer` 中註冊 CORS: ```java @Configuration public class WebConfig implements WebMvcConfigurer { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") // 所有路徑 .allowedOrigins("https://your-frontend.com") // 白名單 .allowedMethods("GET", "POST", "PUT", "DELETE", "OPTIONS") .allowedHeaders("*") .allowCredentials(true); // 若需帶 cookie } } ``` --- ### ✅ 2. 控制在特定 Controller 上(局部 CORS) ```java @CrossOrigin( origins = "https://your-frontend.com", allowCredentials = "true" ) @RestController @RequestMapping("/api") public class ApiController { @GetMapping("/user") public User getUser() { return new User("Alice"); } } ``` --- ### ✅ 3. 搭配 Spring Security(若有) Spring Security 會攔截請求,需加上 CORS 支援: ```java @Configuration @EnableWebSecurity public class SecurityConfig { @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http .cors() // 啟用 CORS .and() .csrf().disable() // 視情況而定 .authorizeHttpRequests() .anyRequest().permitAll(); return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration config = new CorsConfiguration(); config.setAllowedOrigins(List.of("https://your-frontend.com")); config.setAllowedMethods(List.of("GET", "POST", "PUT", "DELETE")); config.setAllowedHeaders(List.of("*")); config.setAllowCredentials(true); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", config); return source; } } ``` --- ## 🧱 CORS 安全實踐(總結) | 安全建議 | 原因 | | ----------------------------------------------------- | -------------------- | | ✅ 明確設定 `allowedOrigins` | 避免任意網站調用 API | | ❌ 避免 `allowedOrigins("*")` + `allowCredentials(true)` | 瀏覽器會拒絕這種不安全組合 | | ✅ 搭配 CSRF / JWT 做身分驗證 | CORS ≠ 認證 | | ✅ 用 HTTPS | 避免中間人竊聽 cookie/token | --- ## 📌 最佳實踐模板 ```java registry.addMapping("/api/**") .allowedOrigins("https://your-frontend.com") .allowedMethods("GET", "POST") .allowCredentials(true); ``` --- ## 🧪 瀏覽器請求示意 ```js // JavaScript(跨來源請求) fetch("https://api.example.com/user", { method: "GET", credentials: "include" // 記得加,才能傳 cookie }); ``` --- ## 🔚 結論 > CORS 是保護用戶資料的「第一道牆」,設定錯了不只是功能壞掉,還可能造成資料洩漏。