在Spring Boot中从Angular 7的请求中接收到空的Authorization标头,但Postman可以正常工作

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

当我向使用Spring Boot设计的后端控制器发送请求时,我收到的授权标头为空。但是,当我使用Postman发送相同的请求时,将命中正确的API,并且将从后端正确获取数据。

在Spring Boot端,这是JwtSecurityConfiguration.java的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    @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();
    }

我在JwtAuthenticationToken.java中收到null授权标头:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    @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);
    }

在等式的Angular端,我使用HTTP拦截器将JWT令牌添加到发送的每个请求中。这是我的HttpInterceptorAuth.service.ts的外观:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
  intercept(request: HttpRequest, next: HttpHandler): Observable<HttpEvent> {
    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);
  }

由于我正在记录HTTP拦截器发送的请求,因此在Chrome控制台中是这样的:

Modified

在Chrome开发者工具的"网络"标签上,这是Chrome发送的请求:
Actual

请注意,OPTIONS请求失败,并显示401 Unauthorized

这可能是因为在后端,当HTTP拦截器已使用Authorization标头中的JWT令牌更新请求时,我收到了一个空的Authorization标头。

我不知道为什么实际发送的请求与HTTP拦截器更新的请求不同。如何解决此问题?


How do I avoid the preflight request check then?

您不能禁用或避免针对CORS起源的预检请求机制。

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

要解决此问题,可以使用CorsConfigurationSource@CrossOrigin

1
2
3
4
5
6
7
8
9
10
11
@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;
    }
1
@CrossOrigin(origins ="*",allowCredentials = ,allowedHeaders = , exposedHeaders = , methods = , value = )

访问控制公开标头