Angular 6 Http Interceptors, request headers not m

2019-03-04 14:16发布

I created an interceptor to add an authorization header to each request sent by the client, here is the code :

import { HttpInterceptor, HttpRequest, HttpHandler, HttpHeaderResponse, HttpSentEvent, HttpProgressEvent, HttpResponse, HttpUserEvent, HttpEvent, HttpHeaders } from "@angular/common/http";
import { Observable } from "rxjs";
import { Injectable } from "@angular/core";

@Injectable()
export class AuthenticationInterceptor implements HttpInterceptor {
    intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
        console.log(localStorage.getItem('jwtToken'));
        if(localStorage.getItem('jwtToken')){
            const request = req.clone({
                setHeaders: {
                    Authorization: `bearer ${localStorage.getItem('jwtToken')}`
                }
            });
            console.log(request.headers.get("Authorization"));
            return next.handle(request);
        }
        return next.handle(req);
    }
}

When a request is sent the function intercept is called and the authorization header is correclty set with the token value in the variable "request" as you can see there : token console screenshot

But the authorization header doesn't appear in the request sent by my browser : network request headers and the backend cannot resolve the token.

Do you know why ?

Here is my spring config:

WebSecurityConfig.java

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)

public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

public final static String AUTHORIZATION_HEADER = "Authorization";

@Autowired
UserService userService;

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.authenticationProvider(getProvider());
}

@Bean
public JwtTokenFilter jwtAuthenticationFilter() {
    return new JwtTokenFilter();
}

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    .csrf()
        .disable()
    .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
    .and()
    .addFilterBefore(jwtAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
    .authorizeRequests()
        .antMatchers("/auth/**")
            .permitAll()
        .anyRequest()
            .authenticated();
}

@Bean
public AuthenticationProvider getProvider() {
    AppAuthProvider provider = new AppAuthProvider();
    provider.setUserDetailsService(userService);
    return provider;
}

@Bean
public PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder();
}

}

CorsConfig.java

@Configuration
public class CorsConfiguration {

        @Bean
        public WebMvcConfigurer corsConfigurer() {
            return new WebMvcConfigurerAdapter() {
                @Override
                public void addCorsMappings(CorsRegistry registry) {
                    registry.addMapping("/**")
                    .allowedOrigins("http://localhost:4200")
                    .allowedMethods("*")
                    .allowedHeaders("*");
                }
            };
        }

}

1条回答
祖国的老花朵
2楼-- · 2019-03-04 14:47

Your problem resides into backend services. For security reasons by default only some headers are accepted, the others are ignored.

To fix your problem you need to setup custom accepted headers. Authorization header, even if is like a standard for JWT, is considered a custom header.

I can give you an example of my Spring Security configuration:

@Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
        config.addAllowedHeader("*");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }

Note the line

config.addAllowedHeader("*");

That means that my REST services accept all possible headers sent by the client. Obviously it's not a good configuration, you should limit allowed headers and other things to match your needs, as restricted as is possible.

Obviously if you don't use Spring Security you need to find the way to do the same thing with yout language/framework.

This is my SecurityConfig.java It's a bit different from yours. Try this and let me know

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private JwtAuthenticationEntryPoint unauthorizedHandler;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Autowired
    private WLUserDetailsService userDetailsService;

    @Value("${jwt.header}")
    private String tokenHeader;

    @Value("${jwt.route.authentication.path}")
    private String authenticationPath;

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService)
                .passwordEncoder(passwordEncoderBean());
    }

    @Bean
    public PasswordEncoder passwordEncoderBean() {
        return new BCryptPasswordEncoder();
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        httpSecurity
                // we don't need CSRF because our token is invulnerable
                .csrf().disable()

                // TODO adjust CORS management
                .cors().and()

                .exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()

                // don't create session
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()

                .authorizeRequests()

                .antMatchers("/auth/**").permitAll()
                .anyRequest().authenticated();

        // Custom JWT based security filter
        JwtAuthorizationTokenFilter authenticationTokenFilter = new JwtAuthorizationTokenFilter(userDetailsService(), jwtTokenUtil, tokenHeader);
        httpSecurity
                .addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

//        // disable page caching
//        httpSecurity
//                .headers()
//                .frameOptions().sameOrigin()  // required to set for H2 else H2 Console will be blank.
//                .cacheControl();
    }

    @Override
    public void configure(WebSecurity web) {
        // AuthenticationTokenFilter will ignore the below paths
        web
                .ignoring()
                .antMatchers(
                        HttpMethod.POST,
                        authenticationPath
                )

                // allow anonymous resource requests
                .and()
                .ignoring()
                .antMatchers(
                        HttpMethod.GET,
                        "/",
                        "/*.html",
                        "/favicon.ico",
                        "/**/*.html",
                        "/**/*.css",
                        "/**/*.js"
                );
    }


    @Bean
    public CorsFilter corsFilter() {
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration config = new CorsConfiguration();
        config.setAllowCredentials(true);
        config.addAllowedOrigin("*");
//        config.addExposedHeader("Authorization, x-xsrf-token, Access-Control-Allow-Headers, Origin, Accept, X-Requested-With, " +
//                "Content-Type, Access-Control-Request-Method, Custom-Filter-Header");
        config.addAllowedHeader("*");
        config.addAllowedMethod("OPTIONS");
        config.addAllowedMethod("GET");
        config.addAllowedMethod("POST");
        config.addAllowedMethod("PUT");
        config.addAllowedMethod("DELETE");
        source.registerCorsConfiguration("/**", config);
        return new CorsFilter(source);
    }

}
查看更多
登录 后发表回答