Spring

중복 로그인 방지 필터

hah 2025. 6. 2. 16:03

1. 개요

로그인 코드를 작성하고 JWT를 활용하여 인증 토큰을 부여하는 코드를 추가했다.

보안 config에서는 각 페이지마다 접근 허용 범위를 설정하여 관리하고 로그인 페이지에서는 토큰이 없어야하기 때문에 모든 접근을 허용했다.

그렇지만 로그인한 상태를 확인할 수 있는 방법은 없어서 필터를 만들어서 확인하기로 했다.

 

 

 

2. 코드 적용

2-1. OncePerRequestFilter

중복로그인 방지 필터는 OncePerRequestFilter를 상속받는다.

 

OncePerRequestFilter는 HTTP 요청 당 단 한 번만 필터 로직을 실행하기 때문에 하나의 요청에 대해 한 번만 실행되는 필터를 만들고 싶을 때 사용한다.

public class JwtLoginBlockFilter extends OncePerRequestFilter

 

doFilterInternal()를 오버라이드 해야한다.

protected void doFilterInternal(HttpServletRequest request,
                                HttpServletResponse response,
                                FilterChain filterChain) throws ServletException, IOException

 

 

 

 

2-2. header에서 authorization 값 받아오기

매개 변수로 받은 서블렛요청에서 header를 가져오며 그 중 jwt 토큰이 저장되는 authorization 값을 가져온다.

 

받아온 authorization 값이 null이면 중복 로그인 필터를 작동하지 않고 다음 필터로 넘어가도록 한다.

즉, 비로그인 상태면 중복 로그인이 아니기 때문에 정상 로그인이 가능하도록 하는 것이다.

String authHeader = request.getHeader(HttpHeaders.AUTHORIZATION);

if(authHeader == null){
    filterChain.doFilter(request, response);
    return;
}

 

 

 

2-3. 조건문으로 토큰 확인하기

요청한 클라이언트의 URI 경로를 가져온다.

 

조건문에서는 가져온 URI 경로가 로그인 페이지이고,

authorization 값이 "Bearer "로 시작하면 즉 JWT 토큰이 포함되어 있으면

403 FORBIDDEN 상태 코드를 반환한다.

String path = request.getRequestURI();

if ("/news-peed/users/login".equals(path)
        && authHeader.startsWith("Bearer ")) {

    response.sendError(HttpServletResponse.SC_FORBIDDEN, "이미 로그인된 사용자입니다.");
    return;
}

 

 

 

2-4. doFilter() 호출

위의 모든 조건들에 해당하지 않은 요청은 중복 로그인 필터를 적용하지 않고 다음 필터를 적용하도록 한다.

해당 doFilter를 적용하지 않으면 요청은 컨트롤러에 도달할 수 없다.

filterChain.doFilter(request, response);

 

 

 

3. 결과

Postman으로 회원가입 -> 로그인 후 발급받은 jwt토큰을 header에 포함해서 재 로그인을 요청한 결과

403 Forbidden 에러 코드가 정상적으로 반환되는 것을 확인하였다.

 

 

 

4. 배운 점

4-1. 필터 안에서는 예외 처리가 불가능하다.

예외처리는 DispatcherServlet 이후에 진행되는데 필터링은 그 전에 이루어지기 때문에 예외 처리가 진행될 수 없다.