ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • bank app 18 - (intercepter 활용)
    spring boot 2023. 4. 21. 10:25
    학습 목표

    1. AuthIntercepter 구현 클래스 만들기
    2. WebMvcConfig 구현 클래스 만들기
    3. 코드 수정 - 인증 처리 일괄 적용 하기
    Spring boot 에서 인터셉터를 적용하는 방법

    implements HandlerInterceptor 를 구현 받는 클래스 만들기
    implements WebMvcConfigurer 를 구현 받는 클래스 만들기

    HandlerInterceptor 는 spring boot  MVC 에서 제공하는 인터셉터로 AOP 개념과는 다르게
    서블릿 필터처럼 동작 합니다. 즉, 클라이언트의 요청이 컨트롤러에 도달하기 전에 인터셉터 요청/응답을 가로채어
    필요한 로직을 수행항 수 있습니다.

    반면, AOP(Aspect-Orented Programming)은 관점 지향 프로그래밍으로 횡단 관심사를 핵심 관심사(core concerns) 분리하여 구현하는 기법입니다.

    따라서 HandlerInterceptor는 AOP 와는 개념적으로 다르지만 AOP와 유사한 효과를 얻을 수 있는 기능 입니다.

    Ecveption Handler 는 AOP와 직접적인 연관은 없습니다. 하지만 spring boot 에서 Exception Handler는
    AOP와 함께 사용되는 개념 중 하나 입니다. 이를 통해서 코드의 가독성과 유지 보수성을 향상 시킬 수 있습니다.
    Spring Boot 에서 Validation 은 AOP 기반으로 동작하는 개념이 맞습니다.
    AOP 는 메서드 호출 전, 혹은 후에 필터링 및 검증 수정 등의 작업을 가능하게 합니다.

     

    세션값이 있는지 유효성 검사를 하는 인터셉터를 만들어준다.

    package com.tenco.bank.handler;
    
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import javax.servlet.http.HttpSession;
    
    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.CustomRestfullException;
    import com.tenco.bank.handler.exception.UnAuthorizedException;
    import com.tenco.bank.repository.model.User;
    import com.tenco.bank.utils.Define;
    
    // 1. HandlerInterceptor 구현
    // 2
    @Component // Ioc 대상 - 싱글톤 관리
    public class AuthInterceptor implements HandlerInterceptor {
    
    	
    	// 컨트롤러 들어가기 전
    	@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) {
    			
    			// 1 단계
    			//response.sendRedirect("/user/sign-in");
    			// 2 단계
    			throw new UnAuthorizedException("로그인 먼저 해주세요", HttpStatus.UNAUTHORIZED);
    			//return false;
    		}
    		return true;
    	}
    	
    	// 요철 처리가 완료된 후, 즉 뷰 렌더링이 완료된 후에 호출되는 메서드
    	@Override
    	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
    			throws Exception {
    		HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
    	}
    }

     

     

    com.tenco.bank안에 config 패키지를 만들어 account or auth 폴더 안에 있는 페이지를 접근할려면

    세션이 있는지 유효성검사를 하게 해준다.

    package com.tenco.bank.config;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    import com.tenco.bank.handler.AuthInterceptor;
    
    @Configuration // Ioc 등록 - 2개 이상 빈으로 등록 될때 사용
    public class WebMvcConfig implements WebMvcConfigurer {
    
    	
    	@Autowired // DI
    	private AuthInterceptor authInterceptor;
    	
    	@Override
    	public void addInterceptors(InterceptorRegistry registry) {
    		registry.addInterceptor(authInterceptor)
    				.addPathPatterns("/account/**")
    				.addPathPatterns("/auth/**"); // 1.path 더 추가 하는 방법
    		// account안에 실행되는것은 인증처리 해줘라
    		
    
    			
    	}
    }

     

     

    세션값이 null 일때 유효성 검사하는 방어적코드를 다 없애준다.

    package com.tenco.bank.controller;
    
    import java.util.List;
    
    import javax.servlet.http.HttpSession;
    import javax.websocket.server.PathParam;
    
    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 com.tenco.bank.dto.DepositFormDto;
    import com.tenco.bank.dto.SaveFormDto;
    import com.tenco.bank.dto.TransferFormDto;
    import com.tenco.bank.dto.WithdrawFormDto;
    import com.tenco.bank.dto.response.HistoryDto;
    import com.tenco.bank.handler.exception.CustomPageException;
    import com.tenco.bank.handler.exception.CustomRestfullException;
    import com.tenco.bank.handler.exception.UnAuthorizedException;
    import com.tenco.bank.repository.model.Account;
    import com.tenco.bank.repository.model.User;
    import com.tenco.bank.service.AccountService;
    import com.tenco.bank.utils.Define;
    
    @Controller
    @RequestMapping("/account")
    public class AccountController {
    	@Autowired
    	private HttpSession session;
    	@Autowired
    	private AccountService accountService;
    	//todo
    	// 계좌목록 페이지
    	// 입금 페이지
    	// 출금 페이지
    	// 이체 페이지
    	// 계좌 상세보기
    	// 계좌 생성 페이지
    	
    	// http:localhost:8080/account/list
    	// http:localhost:8080/account/
    	/**
    	 * 계좌 목록 페이지
    	 * @return 목록 페이지 이동
    	 */
    	@GetMapping({"list", "/"})
    	public String list(Model model) {
    		
    		// todo 예외 테스트 - 삭제 예정
    		//throw new CustomRestfullException("인증되지 않은 사용자 입니다.", HttpStatus.UNAUTHORIZED);
    		//throw new CustomPageException("페이지를 찾을 수 없습니다.", HttpStatus.NOT_FOUND);
    		
    		// prefix
    		// subfix
    		User principal = (User)session.getAttribute(Define.PRINCIPAL);
    		
    		
    		List<Account> accountList = accountService.readAccountList(principal.getId());
    		
    		// accountList에 데이터가 없을때도 있으니 방어적 코드
    		if (accountList.isEmpty()) {
    			model.addAttribute("accountList", null);			
    		}else {
    			model.addAttribute("accountList", accountList);
    		}
    		// View 화면으로 데이터를 내려 주는 기술
    		// Model,ModelAndView
    		// ModelAndView은 동적인 것을 화면에 띄울때 사용한다.
    		return "/account/list";
    	}
    	// 출금 페이지
    	@GetMapping("/withdraw")
    	public String withdraw() {
    		
    		
    		return "/account/withdrawForm";
    	}
    	// 출금 처리기능
    	@PostMapping("/withdraw-proc")
    	public String withdrawproc(WithdrawFormDto withdrawFormDto){
    		
    		User principal = (User)session.getAttribute(Define.PRINCIPAL);
    		if (withdrawFormDto.getAmount() == null) {
    			throw new CustomRestfullException("금액을 입력 하세요.", HttpStatus.BAD_REQUEST);
    		}
    		if (withdrawFormDto.getAmount().longValue() <= 0) {
    			throw new CustomRestfullException("출금액이 0원 이하일 수는 없습니다.", HttpStatus.BAD_REQUEST);
    		}
    		if (withdrawFormDto.getWAccountNumber() == null || withdrawFormDto.getWAccountNumber().isEmpty()) {
    			throw new CustomRestfullException("계좌 번호를 입력 해주세요.", HttpStatus.BAD_REQUEST);
    		}
    		if (withdrawFormDto.getWAccountPassword() == null || withdrawFormDto.getWAccountPassword().isEmpty()) {
    			throw new CustomRestfullException("계좌 비밀 번호를 입력 해주세요.", HttpStatus.BAD_REQUEST);
    		}
    		
    		accountService.updateAccountWithdraw(withdrawFormDto,principal.getId());
    		
    		return "redirect:/account/list";
    		
    	}
    	/**
    	 * 입금처리 기능
    	 * @return
    	 */
    	// 입금 페이지
    	@GetMapping("/deposit")
    	public String deposit() {
    		return "/account/depositForm";
    	}
    	@PostMapping("/deposit-proc")
    	public String depositProc(DepositFormDto depositFormDto) {
    		
    		User user = (User)session.getAttribute(Define.PRINCIPAL);
    		
    		if (depositFormDto.getAmount() == null) {
    			throw new CustomRestfullException("금액을 입력해주세요", HttpStatus.BAD_REQUEST);
    			
    		}
    		if (depositFormDto.getAmount().longValue() <= 0) {
    			throw new CustomRestfullException("입금 금액이 0원 이하일 수 없습니다.", HttpStatus.BAD_REQUEST);
    			
    		}
    		if (depositFormDto.getDAccountNumber() == null) {
    			throw new CustomRestfullException("계좌 번호를 입력하세요", HttpStatus.BAD_REQUEST);
    			
    		}
    		accountService.updateAccountDeposit(depositFormDto);
    		//todo
    		//서비스 호출
    		
    		return "redirect:/account/list";
    	}
    	
    	// 이체 페이지
    	@GetMapping("/transfer")
    	public String transfer() {
    		return "/account/transferForm";
    	}
    	// 이체기능 만들기
    	@PostMapping("/transfer-proc")
    	public String transferProc(TransferFormDto transferFormDto) {
    		
    		User principal = (User)session.getAttribute(Define.PRINCIPAL);
    		// 1.출금 계좌 번호 입력 여부
    		if (transferFormDto.getWAccountNumber() == null || transferFormDto.getWAccountNumber().isEmpty()) {
    			throw new CustomRestfullException("출금 계좌 번호를 입력하세요", HttpStatus.BAD_REQUEST);
    		}
    		// 2. 입금 계좌 번호 입력 여부
    		if (transferFormDto.getDAccountNumber() == null || transferFormDto.getDAccountNumber().isEmpty()) {
    			throw new CustomRestfullException("입금 계좌 번호를 입력하세요", HttpStatus.BAD_REQUEST);
    		}
    		// 3. 출금 계좌 비밀번호 입력 여부
    		if (transferFormDto.getWAccountPassword() == null || transferFormDto.getWAccountPassword().isEmpty()) {
    			throw new CustomRestfullException("출금 계좌 비밀 번호를 입력하세요", HttpStatus.BAD_REQUEST);
    		}
    		// 4. 이체 금액 0원 이상 확인
    		if (transferFormDto.getAmount() <= 0) {
    			throw new CustomRestfullException("이체 금액이 0원 이하일 수 없습니다. ", HttpStatus.BAD_REQUEST);
    		}
    		
    		// 5. 출금 계좌 입금 계좌 번호 동일 여부 확인
    		if (transferFormDto.getWAccountNumber().equals(transferFormDto.getDAccountNumber())) {
    			throw new CustomRestfullException("출금계좌와 입금계좌는 동일할 수 없습니다.", HttpStatus.BAD_REQUEST);
    		}
    		// 서비스 호출
    		accountService.updateAccountTransfer(transferFormDto, principal.getId());
    		
    		
    		return "redirect:/account/list";
    	}
    	
    	// 계좌 생성 페이지
    	@GetMapping("/save")
    	public String save() {
    		// 인증 검사 처리
    		
    		return "/account/saveForm";
    	}
    	/**
    	 * 계좌 생성
    	 * 인증검사
    	 * 유효성 검사 처리 - 0원 입력 가능, 마이너스 입력 불가
    	 * @param saveFormDto
    	 * @return 계좌 목록 페이지
    	 */
    	@PostMapping("/save-proc")
    	public String saveProc(SaveFormDto saveFormDto) {
    		
    		User user = (User)session.getAttribute(Define.PRINCIPAL);
    		if (user == null) {
    			throw new UnAuthorizedException("로그인 먼저 해주세요.",HttpStatus.UNAUTHORIZED);
    		}
    		
    		// 유효성 검사 하기
    		if (saveFormDto.getNumber() == null || saveFormDto.getNumber().isEmpty()) {
    			throw new CustomRestfullException("계좌번호를 입력해주세요", HttpStatus.BAD_REQUEST);
    		}
    		if (saveFormDto.getPassword() == null || saveFormDto.getPassword().isEmpty()) {
    			throw new CustomRestfullException("비밀번호를 입력해주세요", HttpStatus.BAD_REQUEST);
    		}
    		if (saveFormDto.getBalance() == null || saveFormDto.getBalance() < 0) {
    			throw new CustomRestfullException("잘못된 금액 입니다", HttpStatus.BAD_REQUEST);
    		}
    		
    		// 서비스 호출
    		accountService.createAccount(saveFormDto, user.getId());
    		
    		return "redirect:/account/list";
    	}
    	// 계좌 상세 보기 페이지
    	@GetMapping("/detail/{id}")
    	public String detail(@PathVariable Integer id,@RequestParam(name = "type", defaultValue = "all", required = false) String type, Model model) {
    		
    		User principal = (User)session.getAttribute(Define.PRINCIPAL);
    				
    		Account account = accountService.readAccount(id);
    		List<HistoryDto> historyList = accountService.readHistoryListByAccount(type, id);
    		System.out.println(historyList);
    		// 화면을 구성하기 위해 필요한 데이터
    		// 소유자 이름
    		// 계좌번호(1개), 계좌 잔액
    		// 거래 내역
    		model.addAttribute("principal",principal);
    		model.addAttribute("account",account);
    		model.addAttribute("historyList",historyList);
    		
    		return "/account/detail";
    	}
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    	
    }

    'spring boot' 카테고리의 다른 글

    spring boot JPA  (0) 2023.05.09
    bank app 19 - (마이그레이션)  (0) 2023.04.21
    bank app 17 - 계좌 상세보기(2)  (0) 2023.04.20
    bank app 16 - 계좌 상세보기(1)  (0) 2023.04.20
    bank app 10  (0) 2023.04.18
Designed by Tistory.