简体   繁体   中英

Receiving null Authorization header in Spring Boot from requests with Angular 7 but Postman works fine

I am receiving a null Authorization header when I am sending a request to a back-end controller designed with Spring Boot. But when I am sending the same request with Postman, the correct API is hit and data is properly fetched from the back-end.

On the Spring Boot side, here's the code for JwtSecurityConfiguration.java :

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        .csrf().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.OPTIONS, "**/**").permitAll()
        .antMatchers("/auth/**").permitAll()
        .anyRequest().authenticated()
        .and()
        .exceptionHandling().authenticationEntryPoint(entryPoint)
        .and()
        .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

        http.addFilterBefore(authenticationTokenFilter(), UsernamePasswordAuthenticationFilter.class);
        http.headers().cacheControl();
    }

I am receiving the null authorization header in JwtAuthenticationToken.java :

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
            throws AuthenticationException, IOException, ServletException {
        String header = request.getHeader("Authorization");
        if (header == null || !header.startsWith("Bearer ")) {
            System.err.println("Header: " + header);
            LOGGER.error("JWT Token is either missing from HTTP header or has been provided in an incorrect format!");
            throw new AuthenticationCredentialsNotFoundException(
                    "JWT Token is either missing from HTTP header or has been provided in an incorrect format!");
        }
        String authenticationToken = header.substring(7);
        JwtAuthenticationToken jwtAuthenticationToken = new JwtAuthenticationToken(authenticationToken);
        LOGGER.error("JWT Token has been received successfully. Authentication is in progress...");
        return getAuthenticationManager().authenticate(jwtAuthenticationToken);
    }

On the Angular side of the equation, I am using HTTP interceptors to add the JWT token to every request sent. Here's how my HttpInterceptorAuth.service.ts looks:

  intercept(request: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
    let jwtAuthHeader = this._authSvc.getAuthorizedToken();
    let jwtAuthUsername = this._authSvc.getLoggedInUsername();

    if (jwtAuthHeader && jwtAuthUsername) {
      request = request.clone({
        setHeaders: {
          Authorization: jwtAuthHeader
        }
      });
    }
    console.log(request);
    return next.handle(request);
  }

Since I'm logging the request sent by the HTTP interceptor, this is how it is in the Chrome console:

HTTP拦截器拦截后修改请求并添加JWT Auth Token

On the Network tab in Chrome Dev Tools, this is the request that's sent by Chrome: Chrome 发送的实际请求

Notice that the OPTIONS request fails with 401 Unauthorized .

This is probably because on the backend side, I am receiving an empty Authorization header when HTTP Interceptor has updated the request with the JWT Token in Authorization header.

I have no idea why the request that's actually sent is different from the one updated by HTTP interceptor. How can I solve this issue?

How do I avoid the preflight request check then?

You can not disable or avoid the Preflight request mechanism for CORS origins.

Cross-Origin Resource Sharing (CORS) is a mechanism that uses additional HTTP headers to tell browsers to give a web application running at one origin, access to selected resources from a different origin. A web application executes a cross-origin HTTP request when it requests a resource that has a different origin (domain, protocol, or port) from its own

To Resolve that you can use CorsConfigurationSource or @CrossOrigin

@Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("GET", "POST", "PUT", "PATCH", "DELETE", "OPTIONS"));
        configuration.setAllowedHeaders(Arrays.asList("authorization", "content-type", "x-auth-token"));
        configuration.setExposedHeaders(Arrays.asList("x-auth-token"));
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }

@CrossOrigin(origins = "*",allowCredentials = ,allowedHeaders = , exposedHeaders = , methods = , value = )

Access-Control-Expose-Headers

To Resolve that you can use in your controller the annotation:

 @CrossOrigin (origins = "*" , exposedHeaders = "**")

Change * for your origin link, and ** for the specific token to expose.

Example:

@CrossOrigin(origins = "http://localhost:4200", exposedHeaders = "token")
@RestController
public class AuthenticationController {
    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private TokenService tokenService;

    @PostMapping("/auth")
    public ResponseEntity<?> autenticar(@RequestBody @Valid UserDTO userDTO){
        UsernamePasswordAuthenticationToken userData = new UsernamePasswordAuthenticationToken(userDTO.getUserName(), userDTO.getPassword());
        try {
            Authentication authentication = authenticationManager.authenticate(userData);
            String token = tokenService.generateToken(authentication);
            HttpHeaders responseHeaders = new HttpHeaders();
            responseHeaders.set("token", token);

            return ResponseEntity.ok().headers(responseHeaders).build();
        } catch (AuthenticationException e) {
            return ResponseEntity.badRequest().build();
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM