无法调用扩展 (JWT) OncePerRequestFilter。因为@Autowire 失败所以 this.Class 返回 null

Extended (JWT) OncePerRequestFilter cannot be invoked. because @Autowire is failing sothat this.Class is returning null

我目前正在构建一个标准 JwtAuthorizationFilter。为此,我扩展了 OncePerRequestFilter class。此外,我还有一个 JwtUtils class,其中包含所有 JWT 方法。例如,一种方法验证 JWT 不记名令牌。但是,我一直收到无法调用此方法(以及所有其他方法)的错误,因为 this.jwtUtils 为空。

所以基本上我正在尝试 autowire JwtUtils classe。但是 Spring 没有给出任何 instance。相反,它给出 null

那是我的错误信息

Cannot invoke ... jwt.JwtUtils.validateJwtToken(String)" because "this.jwtUtils" is null

JwtAuthorizationFilter class(这里抛出错误)

@Slf4j
public class JwtAuthorizationFilter extends OncePerRequestFilter {

  @Autowired private JwtUtils jwtUtils;
  @Autowired private UserDetailsServiceImpl userDetailsService;

  @Override
  protected void doFilterInternal(
          HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
      throws ServletException, IOException {
    try {
      String jwt = JwtUtils.resolveToken(request);
      System.out.println("before if " + jwt);
      if (jwtUtils.validateJwtToken(jwt)) { // ERROR !
        String username = jwtUtils.getUserNameFromJwtToken(jwt);
        UserDetails userDetails = userDetailsService.loadUserByUsername(username);
        UsernamePasswordAuthenticationToken authentication =
            new UsernamePasswordAuthenticationToken(
                userDetails, null, userDetails.getAuthorities());
        authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

        SecurityContextHolder.getContext().setAuthentication(authentication);
      }

    } catch (Exception e) {
      JwtAuthorizationFilter.log.error("Cannot set user authentication: {}", e.getMessage());
    }
    filterChain.doFilter(request, response);
  }
}

JwtUtils class

import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.UnsupportedJwtException;
import io.jsonwebtoken.security.Keys;
import io.jsonwebtoken.security.SignatureException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.crypto.SecretKey;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;

@Slf4j
@Component
public class JwtUtils {

  @Value("${ggg.app.jwtSecret}")
  private String jwtSecret;

  @Value("${ggg.app.jwtExpirationMs}")
  private long jwtExpirationMs;

  @Value("${ggg.app.jwtRefreshExpirationMs}")
  private long jwtRefreshExpirationMs;

  static String resolveToken(HttpServletRequest req) {
    String bearerToken = req.getHeader("Authorization");
    if (bearerToken != null && bearerToken.startsWith("Bearer ")) return bearerToken.substring(7);
    return null;
  }

  public String generateJwtAccessToken(String username) {
    return generateTokenFromUsername(username, jwtExpirationMs);
  }

  public String generateJwtRefreshToken(String username) {
    return generateTokenFromUsername(username, jwtRefreshExpirationMs);
  }

  private String generateTokenFromUsername(String username, Long expiration) {
    return Jwts.builder()
        .setSubject(username)
        .setIssuedAt(new Date())
        .setExpiration(new Date((new Date()).getTime() + expiration))
        .signWith(secretKey())
        .compact();
  }

  public String getUserNameFromJwtToken(String token) {
    return Jwts.parserBuilder()
        .setSigningKey(secretKey())
        .build()
        .parseClaimsJws(token)
        .getBody()
        .getSubject();
  }

  public boolean validateJwtToken(String token) {
    try {
      Jwts.parserBuilder().setSigningKey(secretKey()).build().parseClaimsJws(token);
      return true;
    } catch (SignatureException e) {
      JwtUtils.log.error("Invalid JWT signature: {}", e.getMessage());
    } catch (MalformedJwtException e) {
      JwtUtils.log.error("Invalid JWT token: {}", e.getMessage());
    } catch (ExpiredJwtException e) {
      JwtUtils.log.error("JWT token is expired: {}", e.getMessage());
    } catch (UnsupportedJwtException e) {
      JwtUtils.log.error("JWT token is unsupported: {}", e.getMessage());
    } catch (IllegalArgumentException e) {
      JwtUtils.log.error("JWT claims string is empty: {}", e.getMessage());
    }
    return false;
  }

  private SecretKey secretKey() {
    return Keys.hmacShaKeyFor(jwtSecret.getBytes());
  }
}

网络安全配置

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

  @Autowired private UserDetailsServiceImpl userDetailsService;

  @Bean
  private static PasswordEncoder passwordEncoder() {
    return new BCryptPasswordEncoder(12);
  }

  @Bean
  private static JwtAuthorizationFilter authenticationJwtTokenFilter() {
    return new JwtAuthorizationFilter();
  }

  //  @Override
  //  public void configure(AuthenticationManagerBuilder authenticationManagerBuilder)
  //      throws Exception {
  //    authenticationManagerBuilder
  //        .userDetailsService(userDetailsService)
  //        .passwordEncoder(WebSecurityConfig.passwordEncoder());
  //  }

  @Bean
  @Override
  public AuthenticationManager authenticationManagerBean() throws Exception {
    return super.authenticationManagerBean();
  }

  @Override
  protected void configure(HttpSecurity http) throws Exception {

    // Disable CSRF (cross site request forgery)
    http.cors()
        .and()
        .csrf()
        .disable()
        // No session will be created or used by spring security
        .sessionManagement()
        .sessionCreationPolicy(SessionCreationPolicy.STATELESS)
        .and()
        .authorizeRequests()
        .antMatchers("/api/v1/auth/**", "/confirm-account")
        .permitAll()
        .anyRequest()
        .authenticated();

    // Apply JWT
    http.addFilterBefore(
        WebSecurityConfig.authenticationJwtTokenFilter(),
        UsernamePasswordAuthenticationFilter.class);
  }
}

问题解决者?

 @Bean
  public JwtAuthorizationFilter authenticationJwtTokenFilter() {
    return new JwtAuthorizationFilter();
  }

我发现私有静态 JwtAuthorizationFilter authenticationJwtTokenFilter() 方法调用问题。如果我将其更改为 public 方法它正在工作,尽管 passwordEncoder 是私有静态的并且在我的身份验证服务中使用。不幸的是,是我的插件导致了这个问题。它会自动更改代码。有人知道该怎么做吗?

授权服务class

@Service
public class AuthService implements AuthServiceRepository {

  @Autowired private RoleRepository roleRepository;
  @Autowired private UserRepository userRepository;
  @Autowired private PasswordEncoder encoder;
  @Autowired private JwtUtils jwtUtils;
  @Autowired private AuthenticationManager authenticationManager;
  @Autowired private UserService userService;
  @Autowired private EmailService emailService;
  @Autowired private ConfirmationTokenRepository confirmationTokenRepository;

@Override
  public JwtResponse signUpUser(SignUpRequest signUpRequest, String siteURL)
      throws MessagingException, UnsupportedEncodingException {
    String accessToken = jwtUtils.generateJwtAccessToken(signUpRequest.getUsername());
    String refreshToken = jwtUtils.generateJwtRefreshToken(signUpRequest.getUsername());
    Set<Role> roles = SignUpRequest.getRoles(signUpRequest, roleRepository);
    AppUser user =
        new AppUser(
            signUpRequest.getUsername(),
            signUpRequest.getEmail(),
                encoder.encode(signUpRequest.getPassword()));
    user.setRoles(roles);

    user.setEnabled(false);
    AppUser newUser = userService.saveUser(user);
    ConfirmationToken confirmationToken = new ConfirmationToken(user);
    confirmationTokenRepository.save(confirmationToken);
    emailService.sendVerificationEmail(user, siteURL, confirmationToken.getConfirmationToken());
    List<String> userRoles =
        newUser.getRoles().stream().map(role -> role.getName().name()).collect(Collectors.toList());

    return new JwtResponse(
        accessToken,
        refreshToken,
        user.getId(),
        signUpRequest.getUsername(),
        signUpRequest.getEmail(),
        userRoles);
  } ... }

那是因为 JwtUtils 和 WebSecurityConfig 没有注册为 Spring Beans。尝试向 类.

添加 @Component 注释

更多关于 Spring 引导中的依赖注入:https://docs.spring.io/spring-boot/docs/current/reference/html/using.html#using.spring-beans-and-dependency-injection