简体   繁体   English

如何修复 Spring 安全授权 header 未通过?

[英]How to fix Spring Security Authorization header not being passed?

In one of my REST services, I make use of Spring Security to validate the token that is being passed in the header.在我的 REST 服务之一中,我使用 Spring 安全性来验证在 header 中传递的令牌。 However, spring is unable to find the "Authorization" header, even though it is there.但是,spring 无法找到“授权”header,即使它在那里。 This was not a problem when testing in test, and even locally but when we deployed to PROD we get this issue.在测试中甚至在本地进行测试时,这不是问题,但是当我们部署到 PROD 时,我们遇到了这个问题。

As an alternative/workaround I removed Spring security and instead tried to do the validation of my token in the actual endpoint before continueing with the rest of the request like such:作为替代/解决方法,我删除了 Spring 安全性,而是尝试在实际端点中验证我的令牌,然后继续使用请求的 rest,如下所示:

@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
}

If I did the above once again it would work in TEST and on LOCAL but not in PROD.如果我再次执行上述操作,它将在 TEST 和 LOCAL 中有效,但在 PROD 中无效。 Error that I would get back would be "Missing Authorization header".我会回来的错误是“缺少授权标头”。 But yet again it is present.但它又一次出现了。 (Tested from postman to). (测试从 postman 到)。

After some research, I saw that I could add ",required=false" so spring would not check for it, but then still there was no token to extract.经过一番研究,我发现我可以添加“,required=false”,这样 spring 就不会检查它,但是仍然没有要提取的令牌。

The only difference between PROD and TEST and my local is the following: PROD 和 TEST 与我的本地之间的唯一区别如下:

Java version java version on test: java version "1.6.0_32" Java 版本 java 版本正在测试: java version "1.6.0_32"

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

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

On Test we use HTTP and PROD it's HTTPS.在测试中,我们使用 HTTP 和 PROD 它是 HTTPS。 Spring Security Version in POM file is 5.2 POM 文件中的 Spring 安全版本为 5.2

EDIT In my web config I do have a section that allows for the "Authorization" header to be present as seen below.编辑在我的 web 配置中,我确实有一个部分允许“授权”header 出现,如下所示。

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

Update On TEST & LOCAL when I iterate through headers in the request filter (as seen below)当我遍历请求过滤器中的标头时更新测试和本地(如下所示)

@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
}

I get the following output.我得到以下 output。 TEST & LOCAL测试和本地

工作测试

On PROD I get the following:在 PROD 上,我得到以下信息:

产品结果

Please help.请帮忙。

After wandering galaxies....在流浪星系之后......

I've fixed it using this:我已经用这个修复了它:

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

Basically you need to enable cors() with the http object.. and then there are multiple ways to handle the cros origin for each controller/method or globally.基本上,您需要使用http object 启用cors() ..然后有多种方法可以为每个控制器/方法或全局处理 cros 来源。

My issue was like this:我的问题是这样的:

Whenever I make request from postman it worked & the "Authorization" key in header was always present, debugged it using request filter just like you.每当我从 postman 发出请求时,它都会起作用,并且 header 中的"Authorization"键始终存在,就像您一样使用请求过滤器对其进行调试。

However, each time request made form front end app (react) the browser prevented the "Authorization" key every single time...但是,每次从前端应用程序(反应)发出请求时,浏览器每次都会阻止"Authorization"键......

To configure it globally:要全局配置它:

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

Or, controller level,或者,controller级别,

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

Ref:参考:

SO answer , Spring Official Guide SO回答Spring官方指南

Possible Issue:可能的问题:

  • Set Authorization in exposed headers,allowed headers list在公开的标头中设置授权,允许的标头列表
  • Set OPTIONS method in setAllowedMethodssetAllowedMethods中设置OPTIONS方法

When using Spring Security with Spring web flux , I had to use the following config to make it work: -当使用Spring SecuritySpring web 通量时,我必须使用以下配置才能使其工作:-

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

}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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