如何修复 Spring Security Authorization 标头未通过?

Posted

技术标签:

【中文标题】如何修复 Spring Security Authorization 标头未通过?【英文标题】:How to fix Spring Security Authorization header not being passed? 【发布时间】:2020-03-13 01:21:36 【问题描述】:

在我的一项 REST 服务中,我使用 Spring Security 来验证在标头中传递的令牌。但是,即使存在“授权”标头,spring 也无法找到它。在测试中甚至在本地进行测试时,这不是问题,但是当我们部署到 PROD 时,我们遇到了这个问题。

作为替代/解决方法,我删除了 Spring 安全性,而是尝试在实际端点中验证我的令牌,然后继续执行其余请求,如下所示:

@PostMapping(value="/create",consumes="application/json; charset=utf-8")
    @CrossOrigin
    public ResponseEntity createAccount(@RequestBody MerchantAccount merchantAccount,@RequestHeader(name="Authorization") String token) 
        log.info("Checking User Token");
        if(!jwtUtil.isAuthorizedToken(token))
            return ResponseEntity.status(401).build();
//some creating Account Logic

如果我再次执行上述操作,它将在 TEST 和 LOCAL 中有效,但在 PROD 中无效。我会回来的错误是“缺少授权标头”。但它又一次出现了。 (从邮递员测试到)。

经过一番研究,我发现我可以添加“,required=false”,这样spring就不会检查它,但是仍然没有要提取的令牌。

PROD 和 TEST 和我本地的唯一区别如下:

Java 版本 java版本测试中:java version "1.6.0_32"

PROD 上的 java 版本:java version "1.8.0_121"

本地java版本:java version "1.8.0_221"

在测试中,我们使用 HTTP 和 PROD,它是 HTTPS。 POM 文件中的 Spring Security 版本为 5.2

编辑 在我的网络配置中,我确实有一个部分允许显示“授权”标题,如下所示。

 @Bean
    public CorsConfigurationSource corsConfigurationSource() 
        final CorsConfiguration configuration = new CorsConfiguration();
        configuration.setAllowedOrigins(ImmutableList.of("*"));//YOLO Allow all origins, we can change this once we go to prod
        configuration.setAllowedMethods(ImmutableList.of("HEAD",
                "GET", "POST", "PUT", "DELETE", "PATCH","OPTIONS"));//Allowed Methods
        configuration.setAllowCredentials(true);
        configuration.setAllowedHeaders(ImmutableList.of("Authorization", "Cache-Control", "Content-Type","Access-Control-Request-Headers","Access-Control-Request-Method",
               "Accept","Access-Control-Allow-Headers"));//Allowed Headers
        final UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    

更新 在 TEST & LOCAL 上,当我遍历请求过滤器中的标头时(如下所示)

@Component
@Service
public class JwtRequestFilter extends OncePerRequestFilter 


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain)
            throws ServletException, IOException 
        logger.info("Done Getting Headers");
        Collections.list(request.getHeaderNames()).forEach(item -> logger.info("header name is " + item));
        logger.info("Done Getting Headers");
        boolean isAccessToken = true;
        final String requestTokenHeader = request.getHeader("authorization");//This is null as the Authorization header is not found in request

我得到以下输出。 测试和本地

在 PROD 上,我得到以下信息:

请帮忙。

【问题讨论】:

标头有实际值吗?可能是空的。如果您在代理/防火墙/负载平衡器/...后面运行。可能是标头已经被阻塞在那里,并且下游服务不再可以访问它(至少这是看起来的样子)。我建议看一下更大的图景(包括基础设施)并绘制差异图。我怀疑你会发现那里有东西阻塞/过滤它。并删除解决方法,如果 Spring Security 无法通过 request.getHeader 获得它,您也不能。 您是否检查了您的 nginx / 代理配置文件是否有可能过滤掉标头的内容? 【参考方案1】:

在流浪星系之后......

我已经用这个修复了它:

@Configuration
@EnableWebSecurity
public class Config extends WebSecurityConfigurerAdapter 
    @Override
    protected void configure(HttpSecurity http) throws Exception 
        http.cors().and() /*.other stuff */;
    

基本上您需要使用http 对象启用cors().. 然后有多种方法可以为每个控制器/方法或全局处理 cros 来源。

我的问题是这样的:

每当我从邮递员发出请求时,它都会起作用并且标题中的 "Authorization" 键始终存在,就像您一样使用请求过滤器对其进行调试。

但是,每次从前端应用程序(反应)发出请求时,浏览器都会阻止"Authorization" 键...

全局配置:

@Bean
public WebMvcConfigurer corsConfigurer() 
    return new WebMvcConfigurer() 
        @Override
        public void addCorsMappings(CorsRegistry registry) 
            registry
                  .addMapping("/greeting-javaconfig")
                  .allowedOrigins("http://localhost:8080");
        
    ;

或者,控制器级别,

@CrossOrigin(origins = "http://localhost:8080")
@GetMapping("/greeting")
public String greeting() 
    return "works!";

参考:

SO answer, Spring Official Guide

【讨论】:

你解决了吗?从 React 发出请求时的授权标头? @UjjwalMishra 是的,我的问题已解决,我正在向 react 提出请求【参考方案2】:

当使用 Spring SecuritySpring web Flux 时,我必须使用以下配置才能使其工作:-

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.web.reactive.EnableWebFluxSecurity;
import org.springframework.security.config.web.server.SecurityWebFiltersOrder;
import org.springframework.security.config.web.server.ServerHttpSecurity;
import org.springframework.security.web.server.SecurityWebFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.reactive.CorsConfigurationSource;
import org.springframework.web.cors.reactive.UrlBasedCorsConfigurationSource;

@EnableWebFluxSecurity
public class WebSecurityConfig 

  @Bean
  public SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) 

    http.cors().and()
        .csrf().disable()
        .authorizeExchange()
        .pathMatchers("/**").permitAll()
        .anyExchange()
        .authenticated()
        .and()
        ... //more mappings 

    return http.build();
  

  @Bean
  CorsConfigurationSource corsConfiguration() 
    CorsConfiguration corsConfig = new CorsConfiguration();
    corsConfig.applyPermitDefaultValues();
    UrlBasedCorsConfigurationSource source =
        new UrlBasedCorsConfigurationSource();
    source.registerCorsConfiguration("/**", corsConfig);
    return source;
  


【讨论】:

以上是关于如何修复 Spring Security Authorization 标头未通过?的主要内容,如果未能解决你的问题,请参考以下文章