已配置跨域仍遭遇CORS错误:Angular调用Spring登录API问题排查
Let's break down why your CORS configuration isn't working and fix it step by step:
Key Issues in Your Current Setup
Conflict Between
AllowCredentialsand Wildcard Origin
You've setconfig.setAllowedOrigins(Collections.singletonList("*"))andconfig.setAllowCredentials(true)in yourCorsFilter. This violates CORS standards: when allowing credentials (like cookies or session data), you can't use a wildcard*for allowed origins—you must specify the exact frontend domain (e.g.,http://localhost:4200for your Angular app).Spring Security Blocking OPTIONS Preflight Requests
CORS preflight requests (of typeOPTIONS) are required for non-simple requests (like your login POST with custom headers). Spring Security blocks these by default unless explicitly allowed.Dual CORS Configurations Causing Conflicts
You have both a globalCorsFilterand a@CrossOriginannotation on your controller. These can override or conflict with each other, leading to inconsistent CORS headers.
Step-by-Step Fixes
1. Correct the Global CORS Filter Configuration
Update your corsFilter() bean to use your actual Angular domain instead of a wildcard, and ensure all necessary headers/methods are allowed:
@Bean public CorsFilter corsFilter() { final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); final CorsConfiguration config = new CorsConfiguration(); // Replace with your Angular app's actual URL (e.g., http://localhost:4200) config.setAllowedOrigins(Arrays.asList("http://localhost:4200")); config.setAllowedHeaders(Arrays.asList("Origin", "Content-Type", "Accept", "Authorization")); config.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "OPTIONS", "DELETE", "PATCH")); config.setAllowCredentials(true); // Expose any custom response headers your frontend needs config.setExposedHeaders(Arrays.asList("Authorization")); source.registerCorsConfiguration("/**", config); return new CorsFilter(source); }
2. Adjust Spring Security to Respect CORS
Modify your SecurityConfiguration to place the CORS filter first in the security chain, allow OPTIONS requests, and make your login endpoint accessible anonymously:
@EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true) public class SecurityConfiguration extends WebSecurityConfigurerAdapter { @Autowired private CorsFilter corsFilter; @Override protected void configure(HttpSecurity http) throws Exception { // Add CORS filter before any security filters http.addFilterBefore(corsFilter, UsernamePasswordAuthenticationFilter.class) .csrf().disable() // Disable CSRF if using JWT (common in Angular-Spring setups) .authorizeRequests() // Allow all OPTIONS preflight requests .antMatchers(HttpMethod.OPTIONS, "/**").permitAll() // Allow unauthenticated access to login endpoint .antMatchers("/gmao/users/login").permitAll() // Require authentication for all other endpoints .anyRequest().authenticated(); } }
3. Remove Controller-Level CORS Annotation
Since you're using a global CORS filter, delete the @CrossOrigin(origins={"*"}) annotation from your UtilisateurController to eliminate configuration conflicts.
4. Update Angular Request to Allow Credentials
Ensure your Angular HttpClient request includes the withCredentials flag to match your backend's AllowCredentials setting:
login(user: User): Observable<User> { return this.http.post(this._baseUrl + 'users/login', user, { withCredentials: true }) .map((response: Response) => { let utilisateur = response.json(); if (utilisateur) { sessionStorage.setItem('currentUser', JSON.stringify(utilisateur)); this.setAuthState(AuthState.LOGGED_IN); } return utilisateur; }); }
Additional Checks
- Verify your browser's console for specific CORS error details (e.g., missing headers, origin mismatches) to fine-tune your configuration.
- For Spring Boot 1.5.x (your version), ensuring the CORS filter is placed before security filters is critical, as older versions handle filter ordering differently than newer Spring Boot releases.
内容的提问来源于stack exchange,提问作者pheromix

