Spring boot 当使用nginix控制器将spring boot应用程序部署到kubernetes群集时,JWT身份验证不起作用

Spring boot 当使用nginix控制器将spring boot应用程序部署到kubernetes群集时,JWT身份验证不起作用,spring-boot,kubernetes,jwt,kubernetes-ingress,nginx-ingress,Spring Boot,Kubernetes,Jwt,Kubernetes Ingress,Nginx Ingress,我有一个SpringBoot应用程序,带有端点POST/login,它验证凭据并在响应头中返回JWT。还有另一个端点/api/cars/listing,它需要具有有效JWT的授权头。此应用程序部署到具有3个节点的Kubernetes群集。之后,我在集群内为L7路由安装了ngnix入口控制器,并添加了入口资源 遵循本教程- 当我使用POST/login生成的JWT并将其用于GET/api/cars/listings时,我在响应中得到了403错误。是否需要在Nginx入口控制器中配置任何东西,以便根

我有一个SpringBoot应用程序,带有端点POST/login,它验证凭据并在响应头中返回JWT。还有另一个端点/api/cars/listing,它需要具有有效JWT的授权头。此应用程序部署到具有3个节点的Kubernetes群集。之后,我在集群内为L7路由安装了ngnix入口控制器,并添加了入口资源

遵循本教程-

当我使用POST/login生成的JWT并将其用于GET/api/cars/listings时,我在响应中得到了403错误。是否需要在Nginx入口控制器中配置任何东西,以便根据请求IP将请求路由到同一节点

kind: Ingress
metadata:
  name: ingress-resource
  annotations:
    kubernetes.io/ingress.class: nginx
    nginx.ingress.kubernetes.io/ssl-redirect: "false"
    nginx.ingress.kubernetes.io/rewrite-target: /$2
spec:
 rules:
 - http:
    paths:
     - path: /jwt(/|$)(.*)
       backend:
        serviceName: jwt-app-service
        servicePort: 80
POST/jwt/login


GET/jwt/api/cars/listings

查看kubectl日志后,发现问题与jwt密钥生成有关。每次spring boot应用程序重新启动时,都会动态生成密钥

我使用的是
Keys.secretKeyFor(SignatureAlgorithm.HS512)在Spring配置文件中,如下所示。可以将其配置为部署环境变量或其他安全方式

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  private final JwtTokenService jwtTokenService;

  private AppUserDetailsService appUserDetailsService;

  @Autowired
  public SecurityConfig(AppUserDetailsService appUserDetailsService) {
    this.jwtTokenService = jwtTokenService();
    this.appUserDetailsService = appUserDetailsService;
  }

  public SecurityConfig() {
    this.jwtTokenService = jwtTokenService();
  }

  private Key base64EncodedSecretKey() {
    return Keys.secretKeyFor(SignatureAlgorithm.HS512);
  }


  private JwtTokenService jwtTokenService() {
    return new JwtTokenService(base64EncodedSecretKey());
  }


  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(this.appUserDetailsService)
        .passwordEncoder(NoOpPasswordEncoder.getInstance());
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.csrf().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.GET,"/greetings").permitAll()
        .antMatchers("/login").permitAll()
        .anyRequest()
        .authenticated()
        .and()
        .addFilterBefore(new LoginFilter("/login", this.jwtTokenService, authenticationManager()),
            UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(new JwtAuthenticationFilter(this.jwtTokenService, "/api/**"), UsernamePasswordAuthenticationFilter.class);


  }
}

查看kubectl日志后,发现问题与JWT密钥生成有关。每次spring boot应用程序重新启动时,都会动态生成密钥

我使用的是
Keys.secretKeyFor(SignatureAlgorithm.HS512)在Spring配置文件中,如下所示。可以将其配置为部署环境变量或其他安全方式

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

  private final JwtTokenService jwtTokenService;

  private AppUserDetailsService appUserDetailsService;

  @Autowired
  public SecurityConfig(AppUserDetailsService appUserDetailsService) {
    this.jwtTokenService = jwtTokenService();
    this.appUserDetailsService = appUserDetailsService;
  }

  public SecurityConfig() {
    this.jwtTokenService = jwtTokenService();
  }

  private Key base64EncodedSecretKey() {
    return Keys.secretKeyFor(SignatureAlgorithm.HS512);
  }


  private JwtTokenService jwtTokenService() {
    return new JwtTokenService(base64EncodedSecretKey());
  }


  @Override
  protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(this.appUserDetailsService)
        .passwordEncoder(NoOpPasswordEncoder.getInstance());
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);

    http.csrf().disable()
        .authorizeRequests()
        .antMatchers(HttpMethod.GET,"/greetings").permitAll()
        .antMatchers("/login").permitAll()
        .anyRequest()
        .authenticated()
        .and()
        .addFilterBefore(new LoginFilter("/login", this.jwtTokenService, authenticationManager()),
            UsernamePasswordAuthenticationFilter.class)
        .addFilterBefore(new JwtAuthenticationFilter(this.jwtTokenService, "/api/**"), UsernamePasswordAuthenticationFilter.class);


  }
}

我猜您的应用程序有问题,因为NGINX几乎不向您的后端服务执行代理传递:请共享您基于JWT的应用程序的更多详细信息或日志application@prometherion是的,你是对的。问题似乎出在应用程序代码本身。JWT签名与本地计算的签名不匹配。无法断言JWT有效性,不应信任JWT有效性。在io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:383)~[jjwt-impl-0.10.5.jar:?]我猜您的应用程序有问题,因为NGINX几乎不执行到后端服务的代理传递:请共享基于JWT的应用程序的更多详细信息或日志application@prometherion是的,你是对的。问题似乎出在应用程序代码本身。JWT签名与本地计算的签名不匹配。无法断言JWT有效性,不应信任JWT有效性。在io.jsonwebtoken.impl.DefaultJwtParser.parse(DefaultJwtParser.java:383)~[jjwt-impl-0.10.5.jar:?]