10/03/2018

스프링 쇼핑몰 만들기 #5. 인터셉터를 이용하여 로그인 여부 및 사용자 구분하기

스프링 쇼핑몰 만들기

#4. 일반 사용자와 관리자 구분에서 일반 사용자 화면과 관리자 화면을 따로 만들었지만, 관리자가 아닌 일반 사용자도 관리자 화면에 직접 주소를 입력해서 접속할 수 있는 문제점이 있습니다.

관리자가 아닌 계정으로 로그인한 뒤, 주소창에 관리자 화면의 주소를 직접 입력하면

아무 문제없이 관리자 화면이 접속됩니다.

심지어 로그인을 하지 않은 상태에서 관리자 화면의 주소를 직접 입력해도

매우 잘 접속됩니다. 자동문..이라기보다 문 자체가 없는 상황이네요.

여기서 인터셉터를 사용합니다.

인터셉터란, 특정 경로를 요청하여 컨트롤러에 접근하는 도중에 가로채서(interceptor) 그 전/후에 실행되는 기능입니다. 다양한곳에 사용될 수 있으며, 특히 로그인의 여부에 대해 사용하기 좋습니다.

예를들어 로그인한 상태에서 장시간 대기상태에 있으면 세션이 만료되어 자동으로 로그아웃이 되지만, 현재 화면에서 다른 페이지로 이동하거나 새로고침을 하지 않는다면 로그인된 상태의 화면이 그대로 보입니다. 이때 회원정보 수정등의 로그인이 필요한 페이지로 이동하게 된다면..? 화면에선 로그인이 되어있는 상태지만, 실제로는 세션이 만료되어 로그아웃되어있는 상태이기 때문에 에러가 발생됩니다.

여기에 인터셉터를 추가하면, 특정 경로의 페이지로 이동되는 순간 세션의 여부를 확인하여 로그인이 되어있다면 컨트롤러로 진행을 계속하고, 로그인이 되어있지 않다면 로그인 페이지로 이동하여 로그인을 진행하게 할 수 있습니다.

interceptor 패키지를 생성한 후, 관리자 여부를 확인해줄 AdminInterceptor.java를 작성합니다.

package com.kubg.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import com.kubg.domain.MemberVO;

public class AdminInterceptor extends HandlerInterceptorAdapter {

 @Override
 public boolean preHandle(HttpServletRequest req,
    HttpServletResponse res, Object obj) throws Exception {
  
  HttpSession session = req.getSession();
  MemberVO member = (MemberVO)session.getAttribute("member");
  
  if(member == null || member.getVerify() != 9) {
   res.sendRedirect("/");
   return false;
  }
  
  return true;
 }
}

AdminInterceptor는 HandlerInterceptorAdapter를 상속받고, 컨트롤러 실행 전에 실행되는 preHandel 메서드와, 컨트롤러 실행 후 실행되는 postHandle로 나뉩니다.

저는 컨트롤러가 실행되기 전에 관리자 여부를 확인하고 싶으니 preHandle을 오버라이드 했습니다.

현재의 세션을 불러와 session 에 저장한 뒤, 그중 member 라는 명칭의 세션을 불러와 MemberVO 의 형태로 변환한 뒤, MemberVO 형태의 변수인 member 에 저장합니다.

조건문을 사용하여 member 에 값이 없는(null) 비 로그인 상태와 member.verify 의 값이 9가 아닐 경우 조건문의 내부가 실행됩니다.

조건문 내부는 가장 처음 화면으로 되돌리는 역할을 하며, false를 반환합니다. preHandle은 반환값이 true이면 컨트롤러로 진행되고, false면 진행이 멈춥니다.

패키지를 추가했으니, 패키지를 인식할 수 있도록 설정을 해주어야하는데, 이때 root-context에서는 설정을 하지 않습니다. 프로젝트가 실행되는 웹환경과 관련된 설정은 root-context가 아닌 servlet-context에서 설정을 해야합니다.

servlet-context에 인터셉터 코드를 추가합니다.

<beans:bean id="AdminInterceptor" class="com.kubg.interceptor.AdminInterceptor" />

<interceptors>
 <interceptor>
  <mapping path="/admin/**" />
  <beans:ref bean="AdminInterceptor" />
 </interceptor>
</interceptors>

가장 먼저 사용할 빈의 이름과 경로를 설정하고, 매핑을 이용해 인터셉터가 실행되는 조건을 만들어줍니다. /admin/** 이므로, /admin 하위의 모든 경로가 포함됩니다. 조건을 작성했으니, 실행될 빈의 이름을 작성하면 끝납니다.

이제 관리자가 아닌 계정으로 로그인한 뒤, 주소창에 직접 관리자 화면을 입력하더라도 접속되지 않으며, 처음 화면으로 이동됩니다.

이걸로 관리자가 아닌 계정으로 관리자 화면에 접속하는것을 막을 수 있게되었습니다. 추가적으로 로그인을 하지 않은 상태에서 관리자 화면에 접속할 때, 처음 화면이 아닌 로그인 화면으로 이동하도록 하겠습니다.

AdminInterceptor의 코드를 수정합니다.

if(member == null) {
 res.sendRedirect("/member/signin");
 return false;
}

member의 값이 없을 때(null)의 상황은 로그인하지 않은 상황이므로, 로그인 화면인 /member/signin으로 이동시킵니다.

로그인하지 않은 상태, 또는 화면엔 로그인이 되어있으나 세션이 만료된 상태에서 관리자 화면인 /admin/index에 접속하려고 하면

이렇게 로그인 화면으로 이동할 수 있습니다.

게시물 수정
  1. 익명6/10/2020

    게시물 잘 보고 있습니다.

    덕분에 웹에 대한 지식이 상당히 늘었습니다.

    답글삭제
  2. 빡세지만 재밋습니다

    답글삭제