2. 토큰 필터 구현

이용준·2023년 9월 30일
0

JWT

목록 보기
2/4

OncePerRequestFilter

개발자되기 (245P)

  • 특징
    - 추상 클래스로 제공되며 매번 동작하는 기본적인 필터
    - 상속으로 구현해서 사용
  • 역할
    - 액세스 토큰값이 담긴 Authorization 헤더값 가져온 뒤 액세스 토큰 유효시 인증 정보 설정

  1. 개발자 되기(234P)
    1. 리프레시 토큰 이후 필터 구현 단계
  • TokenAuthenticationFilter
@RequiredArgsConstructor
public class TokenAuthenticationFilter extends OncePerRequestFilter{

  private final TokenProvider tokenProvider;
  private final static String HEADER_AUTHORIZATION = "Authorization";
  private final static String TOKEN_PREFIX = "Bearer ";

  @Override
  protected void doFilter(HttpServletRequest request,
						  HttpServletResponse response,
						  FilterChain filterChain
						  )throws ServletException, IOException{
	  
	  // 요청 헤더의 Authorization 키 값 조회
	  String authorizationHeader = request.getHeader(HEADER_AUTHORIZATION);
	  // 가져온 값에서 접두사 제거
	  String token = getAccessToken(authorizationHeader);
	  // 가져온 토큰 유효한지 확인, 유효한 경우 인증 정보 설정
	  if(tokenProvider.validToken(token)){
	    Authentication authentication = tokenProvider.getAuthentication(tokne);
	    SecurityContextHolder.getContext().setAuthentication(authentication);
	  }
	  filterChain.doFilter(request, response);
  }

  private String getAccessToken(String authorizationHeader){
  if(authorizationHeader != null && authorizationHeader.startsWith(TOKEN_PREFIX)){
    return authorizationHeader.substring(TOKEN_PREFIX.length());
  }
  return null;
  
  }
}
  1. 요청 헤더의 키가 'Authorization'인 필드값 가져와 접두사 Bearer 제외한 값 추출
  2. 토큰 유효 여부 확인 후 유효시 시큐리티 컨텍스트에서 인증 정보 설정
  3. 컨텍스트 홀더에서 getAuthentication() 메서드 통해 인증 정보 가져오면, 유저 객체 반환
    1. 유저 객체 : 이름, 권한 목록 등의 인증 정보 포함됨.

  1. 코드로 배우는 스프링부트(575P)
    1. API 서버를 위한 필터 구현 단계
  • ApiCheckFilter
    • OncePerRequestFilter 상속받은 filter
@Log4j2
public class ApiCheckFilter extends OncePerRequestFilter{

  private AntPathMatcher antPathMatcher; // 패턴에 맞는 경우 다른 동작 수행
  
  public ApiCheckFilter(String pattern){
    this.antPathMatcher = antPathMatcher;
    this.pattern = pattern;
  }

  @Override
  protected void doFilterInternal(HttpServletRequest request, 
								  HttpServletResponse response,
								  FilterChain filterChain)
								  throws ServletException, IOException{
								  
	log.info("REQUESTURI : "+request.getRequestURI());
	log.info(antPathMatcher.match(pattern, request.getReuqestURI()));
	
	if(antPathMatcher.match(pattern, request.getRequestURI())){
	  log.info(" -- ApiCheckFilter --");
	  return;
	}
	filterChain.doFilter(request, resposne)
  }
}

문자열로 패턴 입력받는 생성자 추가 되었으므로 SecurityConfig를 아래와 같이 수정

@Bean
public ApiCheckFilter apiCheckFilter(){
  return new ApiCheckFilter("/notes/**/*");
}

이후에는 /notes 로 시작하는 경로만 로그 출력됨.

  • ApiLoginFilter
    • 특정 URL로 외부에서 로그인
    • 클라이언트에서 Authorization 헤더 데이터 전송
@Log4j2
public class ApiLoginFilter extends AbstractAuthenticationProcessingFilter{
  private JWTUtil jwtUtil;
  
  public ApiLoginFilter(String defaultFilterProecssUrl, JWTUtil jwtUtil){
    super(defaultFilterProcessUrl);
    this.jwtUtil = jwtUtil;
  }
  
  @Override
  public Authentication attemptAuthentication(HttpServletRequest request, HttpservletResponse response) throws AuthenticationException, IOException, ServletException{
    log.info(" =========== ApiLoginFilter ===========");  
    log.info(" === (ApiLoginFilter) attemptAuthentication ===");
    
    String email = request.getParameter("email");
    String pw = request.getParameter("pw");
    
    if(email==null){
      throw new BadCredentialException("Email cannot be null");
    }
    UsernamePasswordAuthenticationToken authToken = new UsernamePasswordAuthenticationToken(email, pw);
  }
  
  @Override
  protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException{
    log.info(" =========== (ApiLoginFilter) successfulAuthentication ================");  
    log.info(" successfulAuthentication : " + authResult);
    log.info(authResult.getPrincipal());
    
    String email = ((ClubAuthMemberDTO)authResult.getPrincipal()).getUsername();
    String token = null;
    
    try{
      token = jwtUtil.generateToken(email);
      response.setContentType("text/plain");
      response.getOutStream().write(token.getBytes());
      log.info(token);
      
    }catch (Exception e){
      e.printStackTrace();
    }
  }
}
profile
뚝딱뚝딱

0개의 댓글