Spring Security(JWT 실습 사용 클래스 정리)

Rina's·2023년 7월 15일

코드스테이츠

목록 보기
70/96
post-thumbnail

JWT를 정리한 글입니다
주요 클래스와 해당 클래스의 DI 클래스, 사용 메서드를 정리했습니다

🍉SecurityConfiguration

시큐리티필터의 전체적인 설정을 담당하는 클래스

DI

JwtTokenizer
CustomAuthorityUtils

method

  • 1. filterChain()
    HttpSecurity의 속성 값을 설정하여 build하는 메서드

보안에 관련한 설정

커스텀 예외처리 헨들러와 커스텀 필터의 적용

Http요청 권한 설정 메서드

  • 2. passwordEncoder()
    Spring Security에서 사용할 PasswordEncoder를 빈으로 등록하는 메서드
    return PasswordEncoderFactories.createDelegatingPasswordEncoder();
  • 3. corsConfigurationSource()
    CORS정책 설정을 빈으로 등록하는 메서드
    CorsConfigurationSource 를 빈으로 등록 .cors(withDefaults())설정 시 사용
  1. new CorsConfigurationSourcesetAllowedOrigins()/setAllowedMethods()
  2. new UrlBasedCorsConfigurationSourceregisterCorsConfiguration("/**", configuration)
    return UrlBasedCorsConfigurationSource;

🍉CustomFilterConfigurer

extends AbstractHttpConfigurer<CustomFilterConfigurer, HttpSecurity>
SecurityConfiguration의 내부 클래스로, 시큐리티 필터에 추가된 커스텀 필터 클래스

method

  • configure()
    AbstractHttpConfigurer의 메서드를 오버라이딩
    HttpSecurity를 받아 설정을 추가한다
  1. HttpSecuritygetSharedObject()AuthenticationManager
    공통으로 사용되는 인증매니저를 호출한다

JWT인증 필터 등록
2. new JwtAuthenticationFilter(authenticationManager, jwtTokenizer[DI])
.setFilterProcessesUrl("/v11/auth/login"); 필터가 동작하는 엔드포인트 설정
.setAuthenticationSuccessHandler(new MemberAuthenticationSuccessHandler());
.setAuthenticationFailureHandler(new MemberAuthenticationFailureHandler());
해당 필터의 성공/실패 핸들러를 커스텀 핸들러로 설정한다

JWT유효성 필터 등록(인증필터 실행 전 선행)
3. new JwtVerificationFilter(jwtTokenizer[DI], authorityUtils[DI]);
4. builder.addFilter(jwtAuthenticationFilter)
uilder.addFilterAfter(jwtVerificationFilter, JwtAuthenticationFilter.class);
기존 시큐리티필터에 추가한다
addFilter()로 필터를 등록하면 기존 스프링 필터보다 먼저 실행된다
먼저 실행된 필터가 요청을 처리함으로 기존 스프링 필터는 활성되지 않는다

🧊JwtAuthenticationFilter

extends UsernamePasswordAuthenticationFilter
기존 인증필터를 확장하여 기능하는 JWT인증 필터

DI

  • AuthenticationManager 인증
  • JwtTokenizer 토큰 생성

method

  • 1. attemptAuthentication()
    Username, Password을 받아 토큰을 생성하고, 토큰으로 검증된 인증을 만드는 메서드
    HttpServletRequestLoginDtoauthenticationToken
    return authenticationManager.authenticate(authenticationToken);
  • 2. successfulAuthentication()
    검증된 인증을 받아 세부 토큰을 생성하고 헤더에 표시하는 메서드
  1. AuthenticationMemberaccessToken/refreshTokenresponse
  2. getSuccessHandler()
  • 3-1 delegateAccessToken()
    멤버를 받아 Access Token을 생성하는 메서드
    claims의 키 값은 "username"과 "roles", subject는 email
    generateAccessToken() 인자는 username, roles, expiration, base64Key
  1. Memberclaims, subject
  2. JwtTokenizer[DI]getTokenExpiration(), encodeBase64SecretKey()
  3. JwtTokenizer[DI]generateAccessToken() -> AccessToken
  • 3-2 delegateRefreshToken()
    멤버를 받아 Refresh Token을 생성하는 메서드
    subject는 email
    getTokenExpiration()의 인자는
  1. Membersubject
  2. JwtTokenizer[DI]getTokenExpiration(), encodeBase64SecretKey()
  3. JwtTokenizer[DI]generateRefreshToken() -> refreshToken

🧊JwtVerificationFilter

extends OncePerRequestFilter

DI

JwtTokenizer 생성된 토큰 검증용
CustomAuthorityUtils 컨텍스트 저장 인증의 권한 생성용

method

  • 1. shouldNotFilter()
    OncePerRequestFilter 메서드를 오버라이딩(한번 실행되는 요청필터 관련 클래스)
    필터 시작 전 건너뛸지 여부를 확인한다
    HttpServletRequest의 해더에서 인증을 추출한다
    HttpServletRequestAuthorization
    return authorization == null || !authorization.startsWith("Bearer");
  • 2. doFilterInternal()
    OncePerRequestFilter의 메서드를 오버라이딩
    필터 실행 전 요청 헤더에서 claims 추출하여 검증하고 컨텍스트에 저장하는 메서드
    해당 로직에 대한 예외처리를 요청 속성 값으로 설정한다
  1. HttpServletRequestverifyJws() -> setAuthenticationToContext()
  2. try - catch(SignatureException/ExpiredJwtException/Exception){ request.setAttribute()}
  3. filterChain.doFilter()
  • 3. verifyJws()
    요청 헤더의 실제 출력된 값(jws)을 비밀키로 파서를 만들어 검증하는 메서드
    검증에 통과하면 claims을 반환한다
    jws는 Key "Authorization": value 문자열에서 Bearer를 제외한 부분을 추출한다
  1. HttpServletRequestString jws
  2. JwtTokenizer[DI]encodeBase64SecretKey()
  3. return claims jwtTokenizer.getClaims(jws, base64EncodedSecretKey).getBody()
  • 4. setAuthenticationToContext()
    검증된 Authentication를 SecurityContext에 저장하는 메서드
    credentials이 아닌 인증토큰으로 확인하기 때문에 값이 null 이다
    claims String username
    authorityUtils[DI] createAuthorities()
    Authentication authentication = new UsernamePasswordAuthenticationToken(username, null, authorities);
    SecurityContextHolder.getContext().setAuthentication(authentication);

🌻MemberAuthentication(Failure/Success)Handler

implements AuthenticationFailureHandler
implements AuthenticationSuccessHandler
CustomFilterConfigurer의 configure()로 추가된 JwtAuthenticationFilter 처리(인증)가 성공/실패할 경우 실행되는 핸들러

  • onAuthenticationSuccess()
    AuthenticationSuccessHandler 인터페이스의 메서드를 오버라이딩
    에러 로그를 출력하거나, 검증된 인증과 요청 정보를 추가하여 응답을 커스텀 설정할 수 있다
    ex)Authentication/HttpServletRequest
    HttpServletResponse
    ErrorResponse

아래는 인증처리 실패시 보낼 응답을 커스텀하는 예시

🌻MemberAccessDeniedHandler

implements AccessDeniedHandler
권한 외 접근시 호출되는 커스텀 클래스
SecurityFilterChain의 http.accessDeniedHandler() 옵션으로 설정 되었다

method

  • handle()
    AccessDeniedHandler의 메서드를 오버라이딩
    HttpServletRequest, HttpServletResponse, AccessDeniedException을 받는다
    ex)HttpServletRequest/AccessDeniedException
    HttpServletResponse
    ErrorResponse, log.warn()

🌻MemberAuthenticationEntryPoint

implements AuthenticationEntryPoint
미인증시 호출되는 커스텀 클래스
SecurityFilterChain의 http.authenticationEntryPoint() 옵션으로 설정 되었다

method

  • commence()
    HttpServletRequest, HttpServletResponse, AuthenticationException을 받는다
    ex)HttpServletRequest/AuthenticationException
    HttpServletResponse
    ErrorResponse, log.warn()

🌻JwtTokenizer

private String secretKey;
private int accessTokenExpirationMinutes;
private int refreshTokenExpirationMinutes;
Secret Key, access 만료시간, refresh 만료시간에 대한 필드 값
직접 설정하거나 @Value로 프로퍼티에서 받아옴

method

  • 1. encodeBase64SecretKey()
    시크릿 키를 Base64 인코팅하여 사용하기 위한 메서드
    인코팅된 키는 토큰생성이나 검증을 위한 파싱키를 만드는데 사용된다
  • 2. generateAccessToken()
    AccessToken을 만드는 메서드
    claims, subject, expiration, base64EncodedSecretKey를 받아 생성한다
    Jwts.builder()
    .setClaims()
    .setSubject()
    .setIssuedAt()Calendar.getInstance()
    .setExpiration()
    .signWith()getKeyFromBase64EncodedKey()
  • 3. generateRefreshToken()
    RefreshToken을 만드는 메서드
    subject, expiration, base64EncodedSecretKey 받아 생성한다
  • 4. getClaims()
    jws, 인코팅된 SecretKey로 인증토큰을 파싱하여 유효한지 검증한다
    JwtVerificationFilter의 doFilterInternal()에서 호출된다
    String base64EncodedSecretKeyKeyparseClaimsJws(jws)
    return claims;
  • 5. getTokenExpiration()
    만료시간을 추가설정하는 메서드
    JwtAuthenticationFilter의 delegate(Access/Refresh)Token()에서 호출된다
    추가되는 만료시간은 토큰 종류에 따라 필드값으로 설정되어 호출된다
    calendar.add(Calendar.MINUTE, expirationMinutes);
  • 6. getKeyFromBase64EncodedKey()
    암호화된 비밀키로 실제 사용되는 키를 만든다
    키는 토큰 생성이나 검증에 사용된다
    Stringbyte[]decode()Keys.hmacShaKeyFor()return key;
profile
갭린이 리나

0개의 댓글