Spring Boot 在Sping Boot 中从Angular 7的请求中接收null Authorization头,但Postman工作正常

sigwle7e  于 2023-08-04  发布在  Spring
关注(0)|答案(3)|浏览(265)

当我向使用Sping Boot 设计的后端控制器发送请求时,收到空的授权头。但是,当我使用Postman发送相同的请求时,会命中正确的API,并从后端正确地获取数据。
在Sping Boot 端,下面是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();
    }

字符串
我正在接收JwtAuthenticationToken.java中的null授权标头:

@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的外观:

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);
  }


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


的数据
在Chrome开发工具的“网络”选项卡上,这是Chrome发送的请求:


请注意,OPTIONS请求失败,401 Unauthorized失败。
这可能是因为在后端,当HTTP拦截器使用授权头中的JWT令牌更新请求时,我收到了一个空的授权头。
我不知道为什么实际发送的请求与HTTP拦截器更新的请求不同。我该如何解决此问题?

m0rkklqb

m0rkklqb1#

那么我如何避免飞行前请求检查呢?
您不能禁用或避免CORS源的印前检查请求机制。
Cross-Origin Resource Sharing (CORS)是一种机制,它使用额外的HTTP标头来告诉浏览器给予在一个源上运行的Web应用程序提供对来自不同源的选定资源的访问。Web应用程序在请求与其自身来源(域、协议或端口)不同的资源时执行跨来源HTTP请求
要解决这个问题,可以使用CorsConfigurationSource@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;
    }

个字符
Access-Control-Expose-Headers

91zkwejq

91zkwejq2#

要解决您可以在控制器中使用的注解:

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

字符串
将 * 更改为您的源链接,并将**更改为要公开的特定令牌。
示例如下:

@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();
        }
    }
}

dzhpxtsq

dzhpxtsq3#

您还没有在SpringSecurity配置中显式地从授权中排除preflight请求。请记住,默认情况下Spring Security将保护所有端点。
因此,您的API还需要在OPTIONS请求中使用授权令牌。
Spring提供了一个开箱即用的解决方案来从授权检查中排除OPTIONS请求:
JwtSecurityConfiguration.java中,在configure(HttpSecurity http)方法的末尾包含http.cors();。这将把Spring提供的CorsFilter添加到应用程序上下文,绕过OPTIONS请求的授权检查

相关问题