• 티스토리 홈
  • 프로필사진
    Song hyun
  • 방명록
  • 공지사항
  • 태그
  • 블로그 관리
  • 글 작성
Song hyun
  • 프로필사진
    Song hyun
    • 분류 전체보기 (780)
      • 백준 (0)
      • 영어 (2)
        • Diary (0)
        • Toast Masters (2)
      • 메모 (13)
      • 설치 메뉴얼 (30)
      • Java (178)
      • MySQL (60)
      • JSP (67)
      • Springboot (46)
      • HTML,CSS, JS (71)
        • HTML (8)
        • CSS (12)
        • JavaScript (37)
        • HTML&CSS 스터디 (13)
      • C++ (7)
      • Linux (7)
      • JPA (34)
      • Kotlin (2)
      • Flutter (42)
      • Error Note (39)
      • 디자인 패턴 (12)
      • 디지털논리회로 (4)
      • 데이터베이스 시스템 (8)
      • 알고리즘 (7)
      • 운영체제 (3)
      • 이산수학 (3)
      • 인공지능 (1)
      • 자료 구조 (14)
        • 기본 개념 (14)
        • 자료구조 스터디 (0)
      • 💡My project (76)
        • 팩맨 : Java Swing 게임 제작 프로젝트 (6)
        • 네이트톡 : Java 소켓 통신 프로젝트 (4)
        • 포켓옥션 : HikariCP&JDBC CRUD 프.. (3)
        • 이지 부산 : BDIA-Devton 2024 프로.. (20)
        • 그린 유니버시티 : JSP를 사용한 학사관리 프로.. (1)
        • 애드 포커 : 웹 소켓과 Spring을 사용한 카.. (1)
        • 셸위 : 게임 친구 매칭 사이트 (21)
        • 다모아 : 개발자 중개 플랫폼 (20)
      • 📗스터디 (13)
        • CNN : 웹개발 스터디 (10)
        • Node&React로 유튜브 사이트 만들기 (3)
      • 📙독서 및 강연 기록 (36)
        • 강연 (14)
        • 독서 (22)
  • 방문자 수
    • 전체:
    • 오늘:
    • 어제:
  • 최근 댓글
      등록된 댓글이 없습니다.
    • 최근 공지
        등록된 공지가 없습니다.
      # Home
      # 공지사항
      #
      # 태그
      # 검색결과
      # 방명록
      • [Springboot] 30. Intercepter 활용 (인증검사 공통 처리)
        2024년 08월 13일
        • Song hyun
        • 작성자
        • 2024.08.13.:48
        728x90
        반응형

        [Springboot] 30. Intercepter 활용 (인증검사 공통 처리)

         

        1. Intercepter란?

        (1) Intercepter의 개념:

        -인터셉터는 Spring MVC의 핵심 기능 중 하나로, 웹 애플리케이션에서 공통적인 처리를 재사용할 수 있게 해주는 강력한 도구이다.

         

        (2) Intercepter의 활용 사례:

         

        (3) Intercepter의 작동 원리

         

        (4) filter와 intercepter

         

         

        2. Intercepter 사용해보기

        (1) Intercepter 클래스 생성하기

        package com.tenco.bank.handler;
        
        import org.springframework.stereotype.Component;
        import org.springframework.web.servlet.HandlerInterceptor;
        import org.springframework.web.servlet.ModelAndView;
        
        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        
        @Component // IoC 대상(싱글톤 패턴)
        public class AuthIntercepter implements HandlerInterceptor{
        	
        	// prehandle 동작 흐름 (단, 스프링부트 설정 파일/클래스에 등록되어야 한다.)
        	// 컨트롤러 들어오기 전에 동작하는 녀석!
        	// true --> 컨트롤러 안으로 들여 보낸다.
        	// false --> 컨트롤러 안으로 못들어감
        	@Override
        	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        			throws Exception {
        		return HandlerInterceptor.super.preHandle(request, response, handler);
        	}
        	
        	
        	// postHandle
        	// 뷰가 렌더링 되기 바로 전에 콜백되는 메서드
        	@Override
        	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
        			ModelAndView modelAndView) throws Exception {
        		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
        	}
        	
        	
        	// afterCompletion
        	// 요청 처리가 완료된 후, 즉 뷰가 완전 렌더링이 된 후에 호출 된다.
        	@Override
        	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
        			throws Exception {
        		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        	}
        	
        }

         

         

        (2) Controller 전 인증검사 메서드 만들기

        package com.tenco.bank.handler;
        
        import org.springframework.http.HttpStatus;
        import org.springframework.stereotype.Component;
        import org.springframework.web.servlet.HandlerInterceptor;
        import org.springframework.web.servlet.ModelAndView;
        
        import com.tenco.bank.handler.exception.UnAuthorizedException;
        import com.tenco.bank.repository.model.User;
        import com.tenco.bank.utils.Define;
        
        import jakarta.servlet.http.HttpServletRequest;
        import jakarta.servlet.http.HttpServletResponse;
        import jakarta.servlet.http.HttpSession;
        
        @Component // IoC 대상(싱글톤 패턴)
        public class AuthIntercepter implements HandlerInterceptor{
        	
        	// prehandle 동작 흐름 (단, 스프링부트 설정 파일/클래스에 등록되어야 한다.)
        	// 컨트롤러 들어오기 전에 동작하는 녀석!
        	// true --> 컨트롤러 안으로 들여 보낸다.
        	// false --> 컨트롤러 안으로 못들어감
        	@Override
        	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
        			throws Exception {
        		HttpSession session = request.getSession();
        		User principal = (User) session.getAttribute(Define.PRINCIPAL);
        		
        		if(principal == null) {
        			throw new UnAuthorizedException("로그인 먼저 해주세요.", HttpStatus.UNAUTHORIZED);
        		}
        		
        		return true;
        	}
        	
        	
        	// postHandle
        	// 뷰가 렌더링 되기 바로 전에 콜백되는 메서드
        	@Override
        	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
        			ModelAndView modelAndView) throws Exception {
        		HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
        	}
        	
        	
        	// afterCompletion
        	// 요청 처리가 완료된 후, 즉 뷰가 완전 렌더링이 된 후에 호출 된다.
        	@Override
        	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
        			throws Exception {
        		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
        	}
        	
        }

         

         

        (3) WebMvcConfigurer을 구현해 인터셉터 등록하기

        package com.tenco.bank.config;
        
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.context.annotation.Configuration;
        import org.springframework.stereotype.Component;
        import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
        import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
        
        import com.tenco.bank.handler.AuthIntercepter;
        
        import lombok.RequiredArgsConstructor;
        
        @Configuration // <-- 하나의 클래스를 IOC 하고 싶다면 사용
        @RequiredArgsConstructor 
        public class WebMvcConfig implements WebMvcConfigurer {
        	
        	@Autowired // DI
        	private final AuthIntercepter authIntercepter;
        	
        	// @RequiredArgsConstructor <-- 생성자 대신 사용 가능!
        	
        	// 우리가 만든 AuthIntercepter를 등록해야 한다.
        	@Override
        	public void addInterceptors(InterceptorRegistry registry) {
        		registry.addInterceptor(authIntercepter)
        		.addPathPatterns("/account/**")
        		.addPathPatterns("/auth/**");
        	}
        
        }

         

         

        *AccountController 리팩토링

        package com.tenco.bank.controller;
        
        import java.util.Arrays;
        import java.util.List;
        
        import org.springframework.beans.factory.annotation.Autowired;
        import org.springframework.http.HttpStatus;
        import org.springframework.stereotype.Controller;
        import org.springframework.ui.Model;
        import org.springframework.web.bind.annotation.GetMapping;
        import org.springframework.web.bind.annotation.PathVariable;
        import org.springframework.web.bind.annotation.PostMapping;
        import org.springframework.web.bind.annotation.RequestMapping;
        import org.springframework.web.bind.annotation.RequestParam;
        import org.springframework.web.bind.annotation.SessionAttribute;
        import org.springframework.web.servlet.ModelAndView;
        
        import com.tenco.bank.dto.DepositDTO;
        import com.tenco.bank.dto.SaveDTO;
        import com.tenco.bank.dto.TransferDTO;
        import com.tenco.bank.dto.WithdrawalDTO;
        import com.tenco.bank.handler.exception.DataDeliveryException;
        import com.tenco.bank.handler.exception.UnAuthorizedException;
        import com.tenco.bank.repository.interfaces.AccountRepository;
        import com.tenco.bank.repository.interfaces.HistoryRepository;
        import com.tenco.bank.repository.model.Account;import com.tenco.bank.repository.model.HistoryAccount;
        import com.tenco.bank.repository.model.User;
        import com.tenco.bank.service.AccountService;
        import com.tenco.bank.utils.Define;
        
        import jakarta.servlet.http.HttpSession;
        import lombok.RequiredArgsConstructor;
        
        @Controller // IoC 대상(싱글톤으로 관리)
        @RequestMapping("/account")
        @RequiredArgsConstructor
        public class AccountController {
        	
        	private final HttpSession session;
        	private final AccountService accountService;
        
        	
        	/**
        	 * 계좌 생성 페이지 요청
        	 * 주소 설계 : http://localhost:8080/account/save
        	 * @return save.jsp
        	 */
        	@GetMapping("/save")
        	public String savePage() {
        		return "account/save";
        	}
        	
        	
        	/**
        	 * 계좌 생성 기능 요청
        	 * 주소 설계 : http://localhost:8080/account/save
        	 * @param dto
        	 * @return
        	 */
        	@PostMapping("/save")
        	public String saveProc(SaveDTO dto, @SessionAttribute(Define.PRINCIPAL) User principal) {
        		// 1. form 데이터 추출(파싱 전략)
        		// 2. 인증 검사
        		// 3. 유효성 검사
        		// 4. 서비스 호출
        		if(dto.getNumber()==null||dto.getNumber().isEmpty()) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_ACCOUNT_NUMBER, HttpStatus.BAD_REQUEST);
        		}
        		if(dto.getPassword()==null||dto.getPassword().isEmpty()) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_PASSWORD, HttpStatus.BAD_REQUEST);
        		}
        		if(dto.getBalance()==null||dto.getBalance()<=0) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_BALANCE, HttpStatus.BAD_REQUEST);
        		}
        		
        		accountService.createAccount(dto,principal.getId());
        		
        		return "redirect:/account/list";
        	}
        	
        	/**
        	 * 계좌 목록 화면 요청
        	 * 주소 설계: http://localhost:8080/account/list ...
        	 * @return list.jsp
        	 */
        	@GetMapping({"/list","/"})
        	public String listPage(Model model,
        			@RequestParam(name="currentPage", defaultValue="1") Integer currentPage, 
        			@RequestParam(name="totalPage", defaultValue="3") Integer totalPage, 
        			@SessionAttribute(Define.PRINCIPAL) User principal) {
        
        		
        		if(currentPage==null) {
        			currentPage=1;
        		}
        		Integer limit=2; // 한 페이지당 내역 수
        		Integer offset=currentPage; // 몇번부터 뽑을지
        		// 총 내역 수
        		Integer totalAccount=(accountService.readAccountListByUserId(principal.getId())).size();
        		// 총 페이지 수
        		Integer totalPages=(int)Math.ceil((double)totalAccount/limit);
        		
        		// 페이지별 내역 수
        		List<Account> accountList=accountService.readAccountListByUserIdForPaging(principal.getId(),limit,currentPage);
        		if(accountList.isEmpty()) {
        			model.addAttribute("accountList",null);
        		} else {
        			model.addAttribute("accountList",accountList);
        		}
        		
        		
        		model.addAttribute("currentPage", currentPage);
        		model.addAttribute("totalPages", totalPages);
        		model.addAttribute("totalPages", totalPages);
        		// JSP 데이터를 넣어주는 방법
        		return "account/list";
        	}
        	
        	
        	/**
        	 * 출금 페이지 요청
        	 * @return
        	 */
        	@GetMapping("/withdrawal")
        	public String withDrawalPage() {
        		
        		return "account/withdrawal";
        	}
        	
        	/**
        	 * 계좌 출금 요청
        	 * @param dto
        	 * @return
        	 */
        	@PostMapping("/withdrawal")
        	public String withDrawalProc(WithdrawalDTO dto, @SessionAttribute(Define.PRINCIPAL) User principal) {
        		
        		// 유효성 검사 (자바 코드를 개발) --> 스프링부트 @Valid 라이브러리가 존재한다.
        		if(dto.getAmount()==null) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_BALANCE, HttpStatus.BAD_REQUEST);
        		}
        		if(dto.getAmount().longValue()<=0) {
        			throw new DataDeliveryException(Define.W_BALANCE_VALUE, HttpStatus.BAD_REQUEST);
        		}
        		if(dto.getWAccountNumber()==null) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_ACCOUNT_NUMBER, HttpStatus.BAD_REQUEST);
        		}
        		if(dto.getWAccountPassword()==null) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_PASSWORD, HttpStatus.BAD_REQUEST);
        		}
        		
        		accountService.updateAccountWithdrawal(dto, principal.getId());
        		
        		return "redirect:/account/list";
        	}
        	
        	/**
        	 * 입금 페이지 요청
        	 */
        	@GetMapping("/deposit")
        	public String depositPage() {
        				
        		return "account/deposit";
        	}
        	
        	/**
        	 * 
        	 */
        	
        	/**
        	 * 입금 요청 처리
        	 */
        	@PostMapping("/deposit")
        	public String depositProc(DepositDTO dto, @SessionAttribute(Define.PRINCIPAL) User principal) {
        		
        		// 입금시 검사해야 할 것
        		// 1. 계좌가 존재하는지
        		// 2. 돈이 존재하는지
        		
        		if (dto.getAmount() == null) {
                    throw new DataDeliveryException(Define.ENTER_YOUR_BALANCE, HttpStatus.BAD_REQUEST);
                }
        		if(dto.getAmount()<=0) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_BALANCE, HttpStatus.BAD_REQUEST);
        		}
        		if(dto.getDAccountNumber()==null) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_ACCOUNT_NUMBER, HttpStatus.BAD_REQUEST);
        		}
        		
        		accountService.updateAccountDeposit(dto, principal.getId());
        		
        		return "redirect:/account/list";
        	}
        	
        	
        	/**
        	 * 이체 페이지 요청
        	 */
        	@GetMapping("/transfer")
        	public String transferPage() {
        	
        		return "account/transfer";
        	}
        	
        	/**
        	 * 
        	 */
        	
        	/**
        	 * 이체 요청 처리
        	 */
        	@PostMapping("/transfer")
        	public String transferProc(TransferDTO dto, @SessionAttribute(Define.PRINCIPAL) User principal) {
        		
        		// 입금시 검사해야 할 것
        		// 1. 계좌가 존재하는지
        		// 2. 돈이 존재하는지
        		System.out.println(dto);
        		
        		// 입금-출금 계좌 중복 여부 확인 확인
        		if(dto.getDAccountNumber().equals(dto.getWAccountNumber())) {
        			throw new DataDeliveryException(Define.INVALID_INPUT, HttpStatus.BAD_REQUEST);
        		}
        		// 입금 금액 널 확인
        		if (dto.getAmount() == null) {
                    throw new DataDeliveryException(Define.ENTER_YOUR_BALANCE, HttpStatus.BAD_REQUEST);
                }
        		// 입금 금액 - 확인
        		if(dto.getAmount()<=0) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_BALANCE, HttpStatus.BAD_REQUEST);
        		}
        		// 출금 계좌 널 확인
        		if(dto.getDAccountNumber()==null) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_ACCOUNT_NUMBER, HttpStatus.BAD_REQUEST);
        		}
        		// 입금 계좌 널 확인
        		if(dto.getWAccountNumber()==null) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_ACCOUNT_NUMBER, HttpStatus.BAD_REQUEST);
        		}
        		// 출금 계좌 비밀번호 널 확인
        		if(dto.getPassword()==null) {
        			throw new DataDeliveryException(Define.ENTER_YOUR_PASSWORD, HttpStatus.BAD_REQUEST);
        		}
        		
        		accountService.updateAccountTransfer(dto, principal.getId());
        		
        		return "redirect:/account/list";
        	}
        	
        	/**
        	 * 계좌 상세 보기 페이지
        	 * 주소 설계 : http://localhost:800/account/detail/${1}?type=all, deposit, withdraw
        	 * @return
        	 */
        	@GetMapping("/detail/{accountId}")
        	public String detail(@PathVariable(name="accountId") Integer accountId,
        			@RequestParam(required=false, name="type") String type, 
        			@RequestParam(name="page", defaultValue = "1") int page, 
        			@RequestParam(name="size", defaultValue = "2") int size, 
        			Model model) {
        
        		// 유효성 검사
        		// arrays.asList() -> array 선언과 동시에 초기화해주는 메서드
        		// 사용자가 선택한 타입(입출금/입금/출금 검색)을 검사한다.
        		List<String> validTypes=Arrays.asList("all","deposit","withdrawal");
        		if(!validTypes.contains(type)) {
        			throw new DataDeliveryException("유효하지 않은 접근입니다.", HttpStatus.BAD_REQUEST);
        		}
        		
        		// 페이지 개수를 계산하기 위해서, 총 페이지의 수를 계산해주어야 한다.
        		int totalRecords=accountService.countHistoryByAccountIdAndType(type, accountId);
        		int totalPages=(int)Math.ceil((double)totalRecords/size);
        		
        		// 계좌/내역 정보
        		Account account = accountService.readAccountById(accountId);
        		List<HistoryAccount> historyList= accountService.readHistoryByAccountId(type, accountId,page,size);
        		
        
        		model.addAttribute("account",account);
        		model.addAttribute("historyList", historyList);
        		
        		model.addAttribute("currentPage", page);
        		model.addAttribute("totalPages", totalPages);
        		model.addAttribute("type",type);
        		model.addAttribute("size",size);
        		
        		return "account/detail";
        	}
        	
        	
        }
        728x90
        반응형

        'Springboot' 카테고리의 다른 글

        [Springboot] 32. 사용자 비밀번호 암호화 처리  (0) 2024.08.13
        [Springboot] 31. DB 마이그레이션 (H2->MySQL)  (0) 2024.08.13
        [Springboot] 29. 계좌 상세 보기 기능(5단계-계좌 목록 페이징 처리)  (0) 2024.08.12
        [Springboot] 28. 계좌 상세 보기 기능(5단계-정답 코드)  (1) 2024.08.12
        [Springboot] 27. 계좌 상세 보기 기능(5단계-JSTL 사용 및 페이징 기능)  (0) 2024.08.12
        다음글
        다음 글이 없습니다.
        이전글
        이전 글이 없습니다.
        댓글
      조회된 결과가 없습니다.
      스킨 업데이트 안내
      현재 이용하고 계신 스킨의 버전보다 더 높은 최신 버전이 감지 되었습니다. 최신버전 스킨 파일을 다운로드 받을 수 있는 페이지로 이동하시겠습니까?
      ("아니오" 를 선택할 시 30일 동안 최신 버전이 감지되어도 모달 창이 표시되지 않습니다.)
      목차
      표시할 목차가 없습니다.
        • 안녕하세요
        • 감사해요
        • 잘있어요

        티스토리툴바