如何修复 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 标头未通过?的主要内容,如果未能解决你的问题,请参考以下文章

如何在Spring Security中忽略端点?

手动设置spring security auth记住我

如何忽略 Spring Security 中的端点?

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

使用带有spring security的keycloak JWT令牌时如何修复403

如何使用 Spring Boot Security 修复 Spring Boot Webflux 应用程序中的“名称为 requestMappingHandlerAdapter 的 bean 定义无效