spring Sping Boot JWT令牌验证和在微服务中使用声明

sy5wg1nm  于 2023-11-16  发布在  Spring
关注(0)|答案(1)|浏览(140)

我有两个微服务:用户服务和逻辑服务。我希望用户服务的登录/注册等路径是公共的,但逻辑微服务的API要受到保护(至少我正在尝试保护它)。
问题出在逻辑微服务上。所以我想要的是在该服务中获取JWT令牌,验证它(我知道一个密钥)并保存声明稍后使用它们。
我是这样测试的:从我的用户服务获取令牌,然后将请求发送到我的逻辑服务。但问题是,无论出于什么原因,我得到403,即使我调试,它似乎验证令牌刚刚好,甚至记录正确的索赔。
这是我的过滤器:

@Slf4j
public class JwtFilter extends OncePerRequestFilter {

  private final String secretKey;

  public JwtFilter(String secretKey) {
    this.secretKey = secretKey;
  }

  @Override
  public void doFilterInternal(HttpServletRequest httpRequest, HttpServletResponse httpResponse, FilterChain chain)
      throws ServletException, IOException {

   String token = httpRequest.getHeader("Authorization");

    if (token == null || !token.startsWith("Bearer ")) {
      chain.doFilter(httpRequest, httpResponse);
      return;
    }
    else {
      token = token.substring(7);
      Claims claims = Jwts.parser()
          .setSigningKey(secretKey)
          .parseClaimsJws(token)
          .getBody();

      httpRequest.setAttribute("claims", claims);
      chain.doFilter(httpRequest, httpResponse);
      log.info(claims.toString());
      return;
    }
  }
}

字符串
安全配置:

@Configuration
@EnableWebSecurity
@EnableMethodSecurity
public class SecurityConfig {

  @Bean
  public Filter jwtFilter() {
    return new JwtFilter("...");
  }

  @Bean
  public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
    return http
        .csrf(AbstractHttpConfigurer::disable)
        .authorizeHttpRequests(auth ->
            auth.requestMatchers("/api/public/**",
                "/v3/api-docs",
                "/v3/api-docs/**",
                "/swagger-ui/**")
                .permitAll()
                .anyRequest()
                .authenticated())
        .sessionManagement(s -> s.sessionCreationPolicy(SessionCreationPolicy.STATELESS))
        .addFilterBefore(jwtFilter(), UsernamePasswordAuthenticationFilter.class) 
// I also tried to add before BasicAuthenticationFilter.class
        .build();
  }
}


但是当我尝试用有效的jwt token调用安全的API路径时,它的回答是403,即使它验证了token,甚至记录了正确的声明。
我这样发送请求,得到403响应。

curl -v -X 'GET' 'http://localhost:8080/api/...' -H 'accept: */*' -H 'Authorization: Bearer token'


在调试中,它记录了我的声明,然后多次调用BasicErrorController,仅此而已:

INFO 12019 --- [nio-8081-exec-1] k.cloudsoft.products.security.JwtFilter  : {claim1=...}
 DEBUG 12019 --- [nio-8081-exec-1] s.w.s.m.m.a.RequestMappingHandlerMapping : Mapped to org.springframework.boot.autoconfigure.web.servlet.error.BasicErrorController#error(HttpServletRequest)
... // Repeats the same call to #error multiple times


我的控制器是默认的控制器,还没有特定的安全注解。我试着在调试中遵循我的过滤器之后发生的事情,但它只是调用多个过滤器,然后出于某种原因调用错误方法,很难说为什么,因为那里的代码不容易理解,所以如果有人知道如何正确地做,让我知道。

bf1o4zei

bf1o4zei1#

所以我可以通过添加而不是

httpRequest.setAttribute("claims", claims);

字符串
这一点:

Authentication authentication = new UsernamePasswordAuthenticationToken(claims.getSubject(), claims.get("..."), authorities);
SecurityContextHolder.getContext().setAuthentication(authentication);


但仍然感兴趣的是,如果以这种方式在微服务之间使用JWT令牌是一种正常的方式。

相关问题