Postman请求Spring Boot授权头正常,Angular请求授权头为空且遭CORS拦截
错误信息
从源地址'http://localhost:4200'访问'http://localhost:8080/api/v1/users'的XMLHttpRequest被CORS策略阻止:预检请求的响应未通过访问控制检查:请求资源上不存在'Access-Control-Allow-Origin'头。
Angular相关代码
服务代码
getUsersList(): Observable<User[]>{ return this.httpClient.get<User[]>(`${this.baseUrl}`); }
拦截器代码
import { HttpEvent, HttpHandler, HttpInterceptor, HttpRequest, } from '@angular/common/http'; import { Injectable } from '@angular/core'; import { Observable } from 'rxjs'; import { AuthenticationService } from './auth-service'; @Injectable({ providedIn: 'root' }) export class TokenInterceptorService implements HttpInterceptor { constructor(private authService: AuthenticationService) { } intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{ const jwtToken = this.authService.getJwt(); if(jwtToken){ const header = req.clone({ headers: req.headers.set('Authorization', 'Bearer ' + jwtToken) }); console.log(header); return next.handle(header); } return next.handle(req); } }
Spring Boot相关配置
跨域配置
@Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/**") .allowedOrigins("http://localhost:4200") .allowedMethods("*") .allowedHeaders("**") .exposedHeaders("Authorization") .allowCredentials(true) .maxAge(3600); }
安全过滤器配置
public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(csrf -> csrf.disable()) .authorizeRequests() //.requestMatchers("/test").authenticated() .requestMatchers("/api/v1/login/**").permitAll() .requestMatchers("/api/v1/authenticate/get-jwt").permitAll() .requestMatchers("/api/v1/users/**").authenticated() .requestMatchers("/api/v1/user/address/**").authenticated() .anyRequest().authenticated() .and() .exceptionHandling(ex -> ex.authenticationEntryPoint(point)) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class); return http.build(); }
当前问题
使用Postman请求Spring Boot接口时Authorization头非空,但使用Angular请求时该头为空,同时触发上述CORS拦截错误。
解决方案
1. 确保Angular拦截器已正确注册
拦截器需要在应用模块的providers数组中声明才会生效,检查你的app.module.ts是否添加了以下配置:
import { HTTP_INTERCEPTORS } from '@angular/common/http'; import { TokenInterceptorService } from './path/to/token-interceptor.service'; @NgModule({ // ... 其他配置 providers: [ { provide: HTTP_INTERCEPTORS, useClass: TokenInterceptorService, multi: true } ] }) export class AppModule { }
如果缺少这一步,拦截器不会被触发,请求自然不会带上Authorization头。
2. 修复Spring Security的CORS配置
单独通过addCorsMappings配置跨域在Spring Security场景下可能不生效,因为Security过滤器链会优先处理请求,预检的OPTIONS请求可能被拦截。修改安全过滤器配置,添加CORS支持并允许OPTIONS请求:
import org.springframework.web.cors.CorsConfiguration; import org.springframework.web.cors.UrlBasedCorsConfigurationSource; import org.springframework.web.cors.CorsConfigurationSource; import java.util.Arrays; import org.springframework.http.HttpMethod; // ... 其他代码 public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { http.csrf(csrf -> csrf.disable()) .cors(cors -> cors.configurationSource(corsConfigurationSource())) // 启用Security级别的CORS .authorizeRequests() .requestMatchers(HttpMethod.OPTIONS, "/**").permitAll() // 允许所有OPTIONS预检请求 .requestMatchers("/api/v1/login/**").permitAll() .requestMatchers("/api/v1/authenticate/get-jwt").permitAll() .requestMatchers("/api/v1/users/**").authenticated() .requestMatchers("/api/v1/user/address/**").authenticated() .anyRequest().authenticated() .and() .exceptionHandling(ex -> ex.authenticationEntryPoint(point)) .sessionManagement(session -> session.sessionCreationPolicy(SessionCreationPolicy.STATELESS)); http.addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class); return http.build(); } @Bean public CorsConfigurationSource corsConfigurationSource() { CorsConfiguration configuration = new CorsConfiguration(); configuration.setAllowedOrigins(Arrays.asList("http://localhost:4200")); configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "DELETE", "OPTIONS")); configuration.setAllowedHeaders(Arrays.asList("Authorization", "Content-Type")); configuration.setExposedHeaders(Arrays.asList("Authorization")); configuration.setAllowCredentials(true); configuration.setMaxAge(3600L); UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(); source.registerCorsConfiguration("/**", configuration); return source; }
3. 验证Token获取逻辑
在Angular拦截器中添加日志,确认authService.getJwt()确实能返回有效Token:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>>{ const jwtToken = this.authService.getJwt(); console.log("获取到的Token:", jwtToken); // 添加这行日志 // ... 后续代码 }
如果日志显示Token为空,需要检查authService中存储和获取Token的逻辑是否正确。
内容的提问来源于stack exchange,提问作者faisal
相关产品推荐
相关产品推荐

