我有一个带有端点 POST/login 的 Spring boot 应用程序,它验证凭据并在响应 header 中返回 JWT。还有另一个端点/api/cars/listing 需要具有有效 JWT 的授权 header 。该应用程序部署到具有 3 个节点的 Kubernetes 集群。之后,我在集群中安装了用于 L7 路由的 ngnix 入口 Controller ,并添加了入口资源。
遵循本教程 - https://cloud.google.com/community/tutorials/nginx-ingress-gke 。
当我使用从 POST/login 生成的 JWT 并将其用于 GET/api/cars/listings 时,我在响应中收到 403 错误。我需要在 Nginx 入口 Controller 中配置什么才能根据请求 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/登录
获取/jwt/api/cars/listings
最佳答案
查看 kubectl 日志后,发现问题与 JWT key 生成有关。每次 Spring Boot 应用程序重新启动时,都会动态生成 key 。
我在 Spring 配置文件中使用了 Keys.secretKeyFor(SignatureAlgorithm.HS512);
,如下所示。这可以配置为部署环境变量或以其他某种安全方式。
@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);
}
}
关于spring-boot - 当 Spring Boot 应用程序使用 nginx Controller 部署到 kubernetes 集群时,JWT 身份验证不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58400705/