Angular 拦截器:headers 添加到请求中的设置不正确,无法从 API 中获取它们
Angular Interceptor: headers added in the request not set properly, can't fetch them from the API
我正在尝试在我的 angular 拦截器中添加一些自定义 headers,如下所示:
@Injectable()
export class HttpJwtAuthInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
localStorage.setItem('token', 'qsdfqsdfqsdfqsdf');
if (localStorage.getItem('cuid') && localStorage.getItem('token')) {
request = request.clone({
setHeaders: {
'sm_universalid':'blablabla',
Authorization: `Bearer ${localStorage.getItem('token')}`,
},
});
}
return next.handle(request);
}
}
上述拦截器已添加到 app.module.ts:
中的提供程序 属性
providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: HttpJwtAuthInterceptor,
multi: true,
},
{ provide: BASE_PATH, useValue: environment.apiUrl },
],
在我的 spring 启动应用程序中,我添加了一个过滤器来检查是否收到 headers,如果没有收到则抛出异常:
String cuid = request.getHeader(SM_UNIVERSAL_ID);
if (cuid == null || cuid.isEmpty()) {
log.error("Failed authentication: cuid header not found in the request or it is empty");
throw new FailedAuthenticationException("cuid header not found in the request or it is empty:"+cuid);
}
不幸的是,过滤器找不到添加的 headers,我尝试记录收到的 headers 列表,我发现它们被添加为 的值access-control-request-headersheader:
如何分别获得那些 header?以及为什么将它们添加到 access-control-request-headers header?
下面是我的 spring 安全性 class 配置的快照(header 过滤器应用在那里):
@Configuration
@EnableWebSecurity
@Slf4j
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final HeaderVerificationFilter headerVerificationFilter;
private final JwtAuthorizationFilter jwtAuthorizationFilter;
private final JwtAuthEntryPoint jwtAuthenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
//csrf is disabled because we are not using cookies
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//Entry points
http.formLogin().loginProcessingUrl("/api/login").permitAll()
//Disallow everything else
.and().authorizeRequests().anyRequest().authenticated();
//if a user try to access a resource without having enough permissions
http.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);
// Apply Header and JWT filters
http.apply(new JwtTokenFilterConfigurer(headerVerificationFilter, jwtAuthorizationFilter, jwtAuthenticationEntryPoint));
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
@Override
public void configure(WebSecurity web) throws Exception {
// Allow swagger to be accessed without authentication
web.ignoring().antMatchers("/v2/api-docs")//
.antMatchers("/swagger-resources/**")//
.antMatchers("/swagger-ui.html")//
.antMatchers("/configuration/**")//
.antMatchers("/webjars/**")//
.antMatchers("/public");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return authenticationManager();
}
}
我不知道为什么,但我不得不在我的 spring 安全配置 class 中添加我自己的自定义 CORS 策略配置,就像这样:
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// allow requests
config.setAllowedOriginPatterns(List.of("*"));
//allowed methods
config.setAllowedMethods(Arrays.asList("POST", "OPTIONS", "GET", "DELETE", "PUT", "PATCH"));
// headers allow in request
config.setAllowedHeaders(
Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization"));
// headers exposed in response
config.setExposedHeaders(Arrays.asList("Token", "Authorization", "Content-Type", "Content-Disposition"));
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
而且,我必须允许所有类型为 Options 的方法,例如:
@Override
protected void configure(HttpSecurity http) throws Exception {
//csrf is disabled because we are not using cookies
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//Entry points
http.formLogin().loginProcessingUrl("/api/login").permitAll()
//Disallow everything else
.and().authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()//<-- this one
.anyRequest().authenticated();
//if a user try to access a resource without having enough permissions
http.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);
// Apply Header and JWT filters
http.apply(new JwtTokenFilterConfigurer(headerVerificationFilter, jwtAuthorizationFilter, jwtAuthenticationEntryPoint));
}
我正在尝试在我的 angular 拦截器中添加一些自定义 headers,如下所示:
@Injectable()
export class HttpJwtAuthInterceptor implements HttpInterceptor {
constructor() {}
intercept(request: HttpRequest<unknown>, next: HttpHandler): Observable<HttpEvent<unknown>> {
localStorage.setItem('token', 'qsdfqsdfqsdfqsdf');
if (localStorage.getItem('cuid') && localStorage.getItem('token')) {
request = request.clone({
setHeaders: {
'sm_universalid':'blablabla',
Authorization: `Bearer ${localStorage.getItem('token')}`,
},
});
}
return next.handle(request);
}
}
上述拦截器已添加到 app.module.ts:
中的提供程序 属性 providers: [
{
provide: HTTP_INTERCEPTORS,
useClass: HttpJwtAuthInterceptor,
multi: true,
},
{ provide: BASE_PATH, useValue: environment.apiUrl },
],
在我的 spring 启动应用程序中,我添加了一个过滤器来检查是否收到 headers,如果没有收到则抛出异常:
String cuid = request.getHeader(SM_UNIVERSAL_ID);
if (cuid == null || cuid.isEmpty()) {
log.error("Failed authentication: cuid header not found in the request or it is empty");
throw new FailedAuthenticationException("cuid header not found in the request or it is empty:"+cuid);
}
不幸的是,过滤器找不到添加的 headers,我尝试记录收到的 headers 列表,我发现它们被添加为 的值access-control-request-headersheader:
如何分别获得那些 header?以及为什么将它们添加到 access-control-request-headers header?
下面是我的 spring 安全性 class 配置的快照(header 过滤器应用在那里):
@Configuration
@EnableWebSecurity
@Slf4j
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final HeaderVerificationFilter headerVerificationFilter;
private final JwtAuthorizationFilter jwtAuthorizationFilter;
private final JwtAuthEntryPoint jwtAuthenticationEntryPoint;
@Override
protected void configure(HttpSecurity http) throws Exception {
//csrf is disabled because we are not using cookies
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//Entry points
http.formLogin().loginProcessingUrl("/api/login").permitAll()
//Disallow everything else
.and().authorizeRequests().anyRequest().authenticated();
//if a user try to access a resource without having enough permissions
http.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);
// Apply Header and JWT filters
http.apply(new JwtTokenFilterConfigurer(headerVerificationFilter, jwtAuthorizationFilter, jwtAuthenticationEntryPoint));
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(12);
}
@Override
public void configure(WebSecurity web) throws Exception {
// Allow swagger to be accessed without authentication
web.ignoring().antMatchers("/v2/api-docs")//
.antMatchers("/swagger-resources/**")//
.antMatchers("/swagger-ui.html")//
.antMatchers("/configuration/**")//
.antMatchers("/webjars/**")//
.antMatchers("/public");
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return authenticationManager();
}
}
我不知道为什么,但我不得不在我的 spring 安全配置 class 中添加我自己的自定义 CORS 策略配置,就像这样:
@Bean
public FilterRegistrationBean corsFilter() {
UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
CorsConfiguration config = new CorsConfiguration();
config.setAllowCredentials(true);
// allow requests
config.setAllowedOriginPatterns(List.of("*"));
//allowed methods
config.setAllowedMethods(Arrays.asList("POST", "OPTIONS", "GET", "DELETE", "PUT", "PATCH"));
// headers allow in request
config.setAllowedHeaders(
Arrays.asList("X-Requested-With", "Origin", "Content-Type", "Accept", "Authorization"));
// headers exposed in response
config.setExposedHeaders(Arrays.asList("Token", "Authorization", "Content-Type", "Content-Disposition"));
source.registerCorsConfiguration("/**", config);
FilterRegistrationBean bean = new FilterRegistrationBean(new CorsFilter(source));
bean.setOrder(Ordered.HIGHEST_PRECEDENCE);
return bean;
}
而且,我必须允许所有类型为 Options 的方法,例如:
@Override
protected void configure(HttpSecurity http) throws Exception {
//csrf is disabled because we are not using cookies
http.csrf().disable();
// No session will be created or used by spring security
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
//Entry points
http.formLogin().loginProcessingUrl("/api/login").permitAll()
//Disallow everything else
.and().authorizeRequests()
.antMatchers(HttpMethod.OPTIONS, "/**").permitAll()//<-- this one
.anyRequest().authenticated();
//if a user try to access a resource without having enough permissions
http.exceptionHandling().authenticationEntryPoint(jwtAuthenticationEntryPoint);
// Apply Header and JWT filters
http.apply(new JwtTokenFilterConfigurer(headerVerificationFilter, jwtAuthorizationFilter, jwtAuthenticationEntryPoint));
}