본문 바로가기
프로젝트/자리 있어요?

[Refactoring] 22.09.02. Session이 만료되었을 때, Login Filter

by 규글 2022. 9. 2.

 전에 작성했던 추후 해야할 목록에서 이제 두 가지 항목만이 남았다. 하나는 session이 만료되었을 때의 동작, 다른 하나는 DB의 data를 추가, 수정, 삭제하는 과정에서 email 대조 항목이다. 그런데 생각해보면 이들은 로그인 Filter 하나로 해결될 일이지 않을까? 사실 DB의 정보를 추가, 수정, 삭제하는 method를 수행하기 전에 접속한 email과 해당 매장 정보를 대조한다는 것은 Filter 보다는 AOP를 사용하는 것이 맞다. 하지만 이미 매장 관리 페이지로 들어갈 때, session scope에 저장된 접속한 계정을 바탕으로 얻어오는 data이므로 굳이 그런 과정이 필요없을 것 같다는 생각이 들었다. 단순히 session 정보가 만료된 상태로 다른 동작을 하려고 했을 때, 자연히 로그인 페이지로 넘겨주는 것으로 해결될 일이라고 생각한다.

 

 따라서 앞으로도 이 프로젝트를 장난감으로 가지고 놀 수도 있겠지만, 이 게시글이 refactoring의 사실상의 마지막이 될 것 같다.

 

Session에서 접속한 계정의 email 정보가 만료되었을 때

 마이 페이지나 매장 관리 페이지를 일정 시간 열어두고 아무런 작업을 하지 않는 경우에는 session이 만료될 것이다. 그런 상태에서 작업이 수행되는 것은 옳지 못한 동작이 될 것이다. 따라서 session이 만료된 상태에서 로그인이 필요한 동작을 요청했을 경우 session이 만료되었다는 메시지와 함께 로그인 페이지로 이동하도록 할 생각이다. 또 작업 중에는 굉장히 좋지 못한 짓을 많이 했으니, 그에 대한 기록도 하면서 진행하려고 한다.

 

 우선 작업 단계는 다음과 같다.

  • Filter class를 implements 한 class를 만든다.
  • Method를 override 한다.
  • doFilter( ) method에 동작할 내용을 작업한다.
  • 만든 Filter class가 동작할 요청을 class에 @WebFilter annotation을 붙이고 그 속성인 urlPatterns에 작성해준다.

 

 꽤 많은 애를 먹은 것은 doFilter 내부에 동작할 내용을 작성하는 과정이었다. 해당 이미지는 과거 SpringBoot 의 Filter 에 대한 강의를 듣고 정리한 게시글에 첨부한 것이다. Filter라는 것은 그런 것이다. Front로부터 request를 받고, response를 해주는 Back의 가장 바깥쪽에 있는 수문장이라고 생각하면 될 것 같다. 때문에 만약 Filter 단에 걸린다면? 안쪽에서는 아무런 내용을 받을 수가 없는 것이다. Controller에서는 관련 내용을 받을 수 없는 것이다. 하지만 필자는 계속 그것을 망각하고 있었다.

 

 doFilter의 내용만을 한 번에 보기 위해 따로 이미지를 첨부했다. 이곳에서 일어나는 과정은 다음과 같다.

  • 전달받는 ServletRequest 객체를 HttpServletRequest로 casting 한다.
  • HttpSession 정보를 받아 null이 아니면 작업을 통과시킨다.
  • HttpSession 정보가 null이라면 원래의 요청 경로와 query를 받아 encoding 하여 loginform으로의 이동요청에 query로 붙여서 redirect 시킨다.

 

 필자의 망각으로 인한 잘못된 작업은 마지막 줄에 대해서 수행했었다. 필자가 취했던 작업은 다음과 같다. 그로인해 어떤 일이 일어났는지, 어떤 것을 알게 되었는지 적어보겠다.

 

  • 따로 Url과 query를 받는 것이 아니라 getHeader( ) method로 header의 referer 정보를 받으려고 했다.

    사실 이 부분은 받아진다. 하지만 필자는 null 이라는 값을 얻었기 때문에 해당 method를 사용하지 않았다. 그렇다면 어떤 차이가 있었기 때문일까? 해당 내용에 대해 알아보고자 하는 목적은 아니었지만, 검색 중에 발견한 블로그에서 그 이유를 찾을 수 있었다.[각주:1] 주소창에 직접 url을 입력해서 이동한 경우에는 null 값이 들어간다고 한다. 필자의 경우는 session 정보가 만료된 상태로 매장 관리 페이지 간에 이동 요청이 있을 때를 생각하고, 해당 url을 주소창에 직접 요청하면서 테스트를 하고 있었다. 그렇기 때문에 필자는 null 값을 얻고 있던 것이다. 이미지는 테스트를 해서 Filter로 받았을 때 header의 referer 정보를 console창에 출력한 내용이다. 윗줄은 주소창에 요청한 것이 아니고, 아랫줄은 주소창에 직접 요청한 결과이다.
    이를 이용해서 주소창에 직접 입력해서 접근 요청을 하는 것을 막을 수 있겠다. 의도치 않게 하나 알게 된 부분이다.

  • Redirect 전에 HttpServletResponse 객체를 사용해 header에 정보를 담아 전하려고 했다.

    당연히 안된다. HttpServletResponse 객체의 header에 값을 넣으면 그것을 받는 것은 client 쪽이다. 때문에 redirect 요청을 통해 controller에서 HttpServletRequest 객체로 header를 확인하려고 해도 당연히 null 값을 얻을 수밖에 없다. 이미지는 테스트를 위해 url pattern을 임의로 설정하고 console 창에 출력한 내용이다. 윗줄은 Filter에서 받은 header의 referer 정보, 아랫줄은 redirect 전에 header의 test에 값을 넣고 redirect 요청으로 controller에서 받은 header의 test 정보이다.

 Filter를 설정하면서 직접 주소창에 입력해서 테스트하는 바람에 바꾼 controller의 모습이다. 이전에는 loginform으로의 요청 때, 기존 위치로 돌아가기 위해 header의 referer 정보를 받아오는 작업이 되어있다. 그리고 front의 login form element의 요청 주소에 redirect 정보를 넘겨주고 있다. 그렇다면 이 형태가 최선일까?

 

 조금 더 단순하게 생각해본다면 Filter의 urlPattern에 '/seat/users/*' 의 항목을 추가한다면, 어디서든 navigation bar로 로그인 시도를 할 때 Filter를 거치게 된다. 그렇다면 굳이 controller에서는 header의 정보를 얻을 필요가 없어진다. 물론 referer 정보를 사용하지 않아야 하는 경우도 있는 것 같다.[각주:2] 따라서 urlPattern을 새로 추가하고, referer 정보를 받지 않는 것으로 수정하고자 한다.

 

 일단 떠오르는 아이디어가 더 없어 여기까지만 수정하고, 또 다른 생각이 난다면 그 때 작업해보는 것으로 하겠다.

 사실 아직도 이 부분에 대해서 수정해야 할 부분이 많다. 매장 정보를 관리하다가 이동하는 요청에 대해서는 Filter를 통과하지만, 추가나 수정 및 삭제 작업에 대해서는 Filter를 통과하지 않고 있다. 그렇다면 이 모든 내용에 대해 Filter를 통과하도록 해야하는 것일까? 그러기 위해서는 리뷰를 작성, 수정, 삭제하는 service logic을 일반 유저와 매장 관리자의 경우를 구분했어야 할까? 그리고 header의 referer 정보를 사용하지 않는다고 하면, 주소창에 직접 요청을 하는 경우는 어떻게 막을 수 있을까? 여러 고민을 남긴 게시물이다.

댓글