Spring

[Spring] 🔒 Spring Security - CoustomAuthenticationEntryPoint 코드 작성

kyunge_ev 2023. 1. 9. 15:57

 게시판 만들기 구현 중 jwt를 이용해 토큰을 발급받고 이 토큰을 Spring Security로 인증 과정을 거쳐 권한이 있는 사용자만 API를 사용할 수 있게 구현하도록 만들었다. 이 때 사용한 jwtTockenFilter는 아래의 코드와 같다. 

( 📃 OncePerRequestFilter 는 요청이 들어 올 때마다 해당 필터로 인증 과정을 거치게 하는 인터페이스이다. )

 이 때 인증과정에서 실패하거나 인증헤더(Authorization)를 보내지 않게되는 경우 401(UnAuthorized)라는 응답값을 받게 된다.

 이를 처리해주는 로직이 바로 AuthenticationEntryPoint라는 인터페이스인데 이 인터페이스를 커스텀하여 원하는 응답값을 보여주게 하는 것이 CoustomAuthenticationEntryPoint 클래스이다.

 우선, 인증과정에서 에러가 발생하게 되면 AuthenticationEntryPoint 로직을 타게되어, commence라는 메소드를 실행하게 된다. 

 위 인터페이스를 구현하고 commence 메소드를 오버라이딩하여 내가 원하는 에러값을 보여줄 수 있도록 커스텀해보자.

1. AuthenticationEntryPoint 인터페이스를 구현하는 CustomAuthenticationEntryPoint 클래스 생성

2. 인터페이스를 구현하려면 AuthenticationEntryPoint에 있는 commence 메소드를 오버라이딩 해야한다.

 HttpServletRequest로 클라이언트에게서 요청을 받게 됐을 때, jwtTokenFilter에서 발생할 수 있는 에러가 나면invalidTokenException 에러로 응답받게 된다. 이 때 해당 속성값을 가져와 (request.getAttribute("invalidTokenException")) 만들어둔 ErrorCode, Enum 클래스로 형변환 시킨다. 그리고 exception 이라는 변수에 담아 저장한다.

 만약, ErrorCode에서 만들어둔 INVALID_TOKEN과 exception에 담은 에러값이 같다면 setResponse 메소드를 호출한다.

 위의 코드는 jwtTokenFilter에서 authorization에 토큰이 넘어오지 않거나 형식에 맞지 않은 Token이 넘어오면 request.setAttribute()를 사용하여 "invalidTokenException"의 속성값을 ErrorCode.INVALID_TOKEN으로 정의했다.

 그럼 getAttribute를 사용해 가져온 속성값과 내가 정해둔 ErrorCode값이 동일할 것이기 때문에 setResponse 메소드를 호출할 수 있는 것이다.

 위의 코드는 내가 원하는 ErrorCode로 응답을 주기 위해 만들어둔 enum 클래스이다.

 exception에 저장한 에러도 INVALID_TOKEN 에러이고, 내가 저장한 ErrorCode의 에러 상태값도 INVALID_TOKEN 로 똑같기 때문에 setResponse 메소드를 호출한다.

3. setResponse 메소드 호출

 response 와 errorCode를 인자로 넘겨 받은 setResponse 메소드는 인증과정에 에러가 발생할 경우 기본 응답값인 401에러가 아닌 내가 원하는 에러코드와 메시지를 설정할 수 있다.

 reponse의 contentType은 json 타입으로 셋팅해주고, status 상태값은 SC_UNAUTHORIZED로 셋팅해준다.

 JSON 라이브러리에서 제공하는 JSONObject 객체를 사용하여 JSON 데이터를 다룬다. put(key, value)로 데이터를 넣을 수 있다. errorCode로 만들어둔 code 와 message를 .put을 이용하여 JSONObject 객체로 만든 responseJson에 넣어준다.

4. SecurityConfig 클래스

 물론 SecurityConfig 클래스에 시큐리티에 대한 구성정보를 설정할 때, .authenticationEntryPoint로 내가 새로 만들어둔 CustomAuthenticationEntryPoint 객체를 생성해서 넣어줘야 동작할 수 있다.

5. 결과 

 Talend 라는 API Tester를 통해 확인해 본 결과 Authorization에 토큰을 넘기지 않았을 때, 내가 커스텀 해둔 code와 message가 JSON 데이터 형식으로 반환되어 응답한다.