JAVA

스프링부트 블로그 – 인터셉터 적용하기

blog app

스프링부트 블로그 – 인터셉터 적용하기

인터셉터에는 다양한 패턴이 있는데 대표적으로 Code Grant Type과 Client Credentials Grant Type이 있다. Client Credentials Grant Type은 휴대폰 앱이나 리액트 등에서 사용된다. 이 포스팅에서는 Code Grant Type으로 인터셉터를 적용한다.

spring
스프링부트 공통기능 처리(Filter,Interceptor,AOP)프로그램을 개발하다보면 공통적으로 처리해야할 기능들이 많다. 예를 들어 로그인 관련 처리, 권한체크, 보안, pc와 모바일웹의 분기처리, 페이지 인코딩 변환 등이 있다. 이러한 공통적인 코드는 모든 트렌젝션마다 관리하는 것 보다 트렌젝션이 이루어지기 전에 미리 필터링하면 서버의 부하를 줄일 수 있으며 중복된 코드를 제거할 수 있다....

인테셉터 적용하기

1.handler 패키지에 인터셉터 클래스 SessionInterceptor.java를 만든다.
package com.cos.blogapp.handler;

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

import org.springframework.web.servlet.HandlerInterceptor;

import com.cos.blogapp.domain.user.User;

public class SessionInterceptor implements HandlerInterceptor {
  
  @Override
  public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
      throws Exception {
    System.out.println("prehandle실행됨");
    
    HttpSession session = request.getSession();
    User principal = (User) session.getAttribute("principal");
 		if(principal == null) {
 			response.sendRedirect("/loginForm"); // filter에서는 throw를 던질 수 없기 때문에 여기서도 평소에 throw 안쓰도록 함
 		}
 		
    return true;
  }
  
}

 

2.Controller 파일에서 인증 체크를 할 주소에 /api를 추가한다.
package com.cos.blogapp.web;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.DeleteMapping;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cos.blogapp.domain.user.User;
import com.cos.blogapp.handler.ex.MyAsyncNotFoundException;
import com.cos.blogapp.handler.ex.MyNotFoundException;
import com.cos.blogapp.service.BoardService;
import com.cos.blogapp.service.CommentService;
import com.cos.blogapp.util.Script;
import com.cos.blogapp.web.dto.BoardSaveReqDto;
import com.cos.blogapp.web.dto.CMRespDto;
import com.cos.blogapp.web.dto.CommentSaveReqDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor 
@Controller 
public class BoardController {

  // DI : Ioc에 있는거 가져옴
  private final BoardService boardService;
  private final CommentService commentService;
  private final HttpSession session;
  
  // 댓글달기
  @PostMapping("/api/board/{boardId}/comment")
  public String commentSave(@PathVariable int boardId, CommentSaveReqDto dto) {
    User principal = (User) session.getAttribute("principal");
    
    commentService.댓글등록(boardId, dto, principal); // -> 디비와 관련된 트랜젝션을 서비스로 이동 
    return "redirect:/board/"+boardId;  
  }
  
  // 게시글 수정하기
  @PutMapping("/api/board/{id}")
  public @ResponseBody CMRespDto<String> update(@PathVariable int id, 
      @RequestBody @Valid BoardSaveReqDto dto, BindingResult bindingResult){

    //유효성검사
    if (bindingResult.hasErrors()) {
      Map<String, String> errorMap = new HashMap<>();
      for (FieldError error : bindingResult.getFieldErrors()) {
        errorMap.put(error.getField(), error.getDefaultMessage());
      }
      throw new MyAsyncNotFoundException(errorMap.toString());
    }
    
    User principal = (User) session.getAttribute("principal");
    
    boardService.게시글수정(id, principal, dto);
    
    return new CMRespDto<String>(1, "업데이트 성공",null);
    
  }

  // 게시글 수정하기 페이지 이동
  @GetMapping("/api/board/{id}/updateForm")
  public String boardUpdateForm(@PathVariable int id, Model model) {
    
    model.addAttribute("boardEntity", boardService.게시글수정페이지이동(id, model));
    
    return "board/updateForm";
    
  }

  // 게시글 삭제하기 
  @DeleteMapping("/api/board/{id}")
  public @ResponseBody CMRespDto<String> deleteById(@PathVariable int id) {
    User principal = (User) session.getAttribute("principal");
    
    boardService.게시글삭제(id, principal);
    
    return new CMRespDto<String>(1, "성공", null);
  }

  // 게시글 상세보기 
  @GetMapping("/board/{id}") 
  public String detail(@PathVariable int id, Model model) {
    // Board객체에 존재하는 것(Board(o),User(o),List<Comment>(x : LAZY))
    model.addAttribute("boardEntity", boardService.게시글상세보기(id, model));
    return "board/detail"; 
  }

  // 게시글 등록하기
  @PostMapping("/api/board")
  public @ResponseBody String save(@Valid BoardSaveReqDto dto, BindingResult bindingResult) {

    User principal = (User) session.getAttribute("principal");

    if (bindingResult.hasErrors()) {
      Map<String, String> errorMap = new HashMap<>();
      for (FieldError error : bindingResult.getFieldErrors()) {
        errorMap.put(error.getField(), error.getDefaultMessage());
      }
      return Script.back(errorMap.toString());
    }

  // 핵심 로직 
    boardService.게시글등록(principal, dto);
    
    return Script.href("/", "글쓰기 성공");
  }

  // 게시글 등록하기 페이지 이동하기
  @GetMapping("/board/saveForm")
  public String saveForm() {
    return "/board/saveForm";
  }

  // 게시글 목록보기 
  @GetMapping("/board")
  public String home(Model model, int page) {
    model.addAttribute("boardsEntity", boardService.게시글목록보기(page));
    return "board/list";
  }

}
package com.cos.blogapp.web;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpSession;
import javax.validation.Valid;

import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
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.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cos.blogapp.domain.user.User;
import com.cos.blogapp.domain.user.UserRepository;
import com.cos.blogapp.handler.ex.MyAsyncNotFoundException;
import com.cos.blogapp.service.UserService;
import com.cos.blogapp.util.MyAlgorithm;
import com.cos.blogapp.util.SHA;
import com.cos.blogapp.util.Script;
import com.cos.blogapp.web.dto.CMRespDto;
import com.cos.blogapp.web.dto.JoinReqDto;
import com.cos.blogapp.web.dto.LoginReqDto;
import com.cos.blogapp.web.dto.UserUpdateDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Controller
public class UserController {

  // DI
  private final UserService userService;
  private final HttpSession session;

  // 회원정보 수정 
  @PutMapping("/api/user/{id}")
  public @ResponseBody CMRespDto<String> update(@PathVariable int id, @Valid @RequestBody UserUpdateDto dto, BindingResult bindingResult) {

    //유효성검사
    if (bindingResult.hasErrors()) {
      Map<String, String> errorMap = new HashMap<>();
      for (FieldError error : bindingResult.getFieldErrors()) {
        errorMap.put(error.getField(), error.getDefaultMessage());
      }
      throw new MyAsyncNotFoundException(errorMap.toString());
    }
    
    User principal = (User) session.getAttribute("principal");
    
    //권한 체크
    if (principal.getId() != id) {
      throw new MyAsyncNotFoundException("회원정보를 수정할 권한이 없습니다.");
    }

  // 핵심로직 
    userService.회원수정(principal, dto);
    
    // 세션 동기화 해주는 부분 
    principal.setEmail(dto.getEmail());
    session.setAttribute("principal", principal); 
    
    return new CMRespDto<String>(1,"성공",null);
    
  }

  // 회원정보 보기 
  @GetMapping("/api/user/{id}")
  public String userInfo(@PathVariable int id) {
    return "user/updateForm";
  }

  // 로그아웃 
  @GetMapping("/logout")
  public String logout() {
    session.invalidate(); 
    return "redirect:/";
  }

  // 로그인 페이지 이동 
  @GetMapping("/loginForm")
  public String login() {
    return "/user/loginForm";
  }

  // 회원가입 페이지 이동 
  @GetMapping("/joinForm")
  public String joinForm() {
    return "/user/joinForm";
  }

  // 회원가입 
  @PostMapping("/join")
  public @ResponseBody String join(@Valid JoinReqDto dto, BindingResult bindingResult) {

    // 실패했을 때
    if (bindingResult.hasErrors()) {
      Map<String, String> errorMap = new HashMap<>();
      for (FieldError error : bindingResult.getFieldErrors()) {
        errorMap.put(error.getField(), error.getDefaultMessage());
      }
      return Script.back(errorMap.toString());
    }

    userService.회원가입(dto);
    return Script.href("/loginForm");
  }

  // 로그인 
  @PostMapping("/login")
  public @ResponseBody String login(@Valid LoginReqDto dto, BindingResult bindingResult) {

    // 실패했을 때
    if (bindingResult.hasErrors()) {
      Map<String, String> errorMap = new HashMap<>();
      for (FieldError error : bindingResult.getFieldErrors()) {
        errorMap.put(error.getField(), error.getDefaultMessage());
      }
      return Script.back(errorMap.toString());
    }

    User userEntity = userService.로그인(dto);

    if (userEntity == null) { 
      return Script.back("아이디 혹은 비밀번호를 잘못 입력하였습니다.");
    } else {
      session.setAttribute("principal", userEntity);
      return Script.href("/", "로그인 성공");
    }

  }

}
package com.cos.blogapp.web;

import javax.servlet.http.HttpSession;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.ResponseBody;

import com.cos.blogapp.domain.user.User;
import com.cos.blogapp.handler.ex.MyAsyncNotFoundException;
import com.cos.blogapp.service.CommentService;
import com.cos.blogapp.web.dto.CMRespDto;

import lombok.RequiredArgsConstructor;

@RequiredArgsConstructor
@Controller
public class CommentController {
  
  private final CommentService commentService;
  private final HttpSession session;
  
  @DeleteMapping("/api/comment/{id}")
 	public @ResponseBody CMRespDto<?> deleteById(@PathVariable int id){
 		User principal = (User) session.getAttribute("principal");

 		commentService.댓글삭제(id, principal);
 		return new CMRespDto<>(1, "성공", null);
 	}
  
}

 

최신글