두번째 BeanCreationException

채정윤·2025년 5월 13일

Error

목록 보기
5/9

JwtTokenProvider라는 빈(Bean)을 생성하는 과정에서 BeanCreationException이 발생

문제의 핵심 :

JwtTokenProvider의 인스턴스화 실패

  • 이러한 문제의 일반적인 원인
    • JwtTokenProvider 클래스의 생성자 내부에서 예외가 발생하는 경우
    • JWT(JSON Web Token) 생성 및 검증에 필요한 시크릿 키(secret key)가 설정되지 않았거나 잘못 설정된 경우
    • 필요한 다른 빈(Bean)에 대한 의존성이 누락된 경우
    • 애플리케이션 설정 속성(application.properties 또는 application.yml)이 누락된 경우
  • 두 가지 주요 조치
    1. JWT 설정 추가: application.properties (또는 application.yml) 파일에 JWT 시크릿 키와 만료 시간을 정의하는 속성(예: jwt.secret=your-secret-key, jwt.expiration=86400000)을 추가

    2. JwtTokenProvider 클래스 코드 수정 제안:

      • @Component 어노테이션을 사용하여 Spring이 이 클래스를 빈으로 관리
      • @RequiredArgsConstructor (Lombok) 를 통해 의존성을 주입
      • @Value 어노테이션을 사용하여 application.properties에 설정된 JWT 관련 값들(시크릿 키, 만료 시간)을 클래스 필드에 주입
      • @PostConstruct 어노테이션이 붙은 메소드 내에서 시크릿 키를 Base64로 인코딩하여 보안을 강화
      • JWT 토큰 생성(createToken), 토큰으로부터 인증 정보 획득(getAuthentication), 토큰에서 사용자 이름 추출(getUsername), 권한 정보 추출(getAuthorities), 토큰 유효성 검증(validateToken) 등의 메소드 추가
          @PostConstruct
          protected void init() {
              secretKey = Base64.getEncoder().encodeToString(secretKey.getBytes());
          }
      
          public String createToken(String username, List<String> roles) {
              Claims claims = Jwts.claims().setSubject(username);
              claims.put("roles", roles);
      
              Date now = new Date();
              Date validity = new Date(now.getTime() + validityInMilliseconds);
      
              return Jwts.builder()
                      .setClaims(claims)
                      .setIssuedAt(now)
                      .setExpiration(validity)
                      .signWith(Keys.hmacShaKeyFor(secretKey.getBytes()))
                      .compact();
          }
      
          public Authentication getAuthentication(String token) {
              String username = getUsername(token);
              UserDetails userDetails = new User(username, "", getAuthorities(token));
              return new UsernamePasswordAuthenticationToken(userDetails, "", userDetails.getAuthorities());
          }
      
          public String getUsername(String token) {
              return Jwts.parserBuilder()
                      .setSigningKey(Keys.hmacShaKeyFor(secretKey.getBytes()))
                      .build()
                      .parseClaimsJws(token)
                      .getBody()
                      .getSubject();
          }
      
          private Collection<? extends GrantedAuthority> getAuthorities(String token) {
              Claims claims = Jwts.parserBuilder()
                      .setSigningKey(Keys.hmacShaKeyFor(secretKey.getBytes()))
                      .build()
                      .parseClaimsJws(token)
                      .getBody();
      
              List<String> roles = claims.get("roles", List.class);
              return roles.stream()
                      .map(SimpleGrantedAuthority::new)
                      .collect(Collectors.toList());
          }
      
          public boolean validateToken(String token) {
              try {
                  Jwts.parserBuilder()
                          .setSigningKey(Keys.hmacShaKeyFor(secretKey.getBytes()))
                          .build()
                          .parseClaimsJws(token);
                  return true;
              } catch (JwtException | IllegalArgumentException e) {
                  return false;
              }
          }

0개의 댓글