[Practice] 인터셉터 활용 (2)
2021. 4. 20. 00:10ㆍSpring/Practice
1. 문제
- 인터셉터를 이용하여 JWT 인증이 필요한 API 에 대해서(글쓰기) 토큰 유효성을 검증하는 API
- 게시글 작성 기능 구현 ("/api/board")
- 글쓰기 API 호출 시 토큰 유효성 검사
2. 풀이
- BoardInput.java
package com.example.jpa.sample.board.model;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@AllArgsConstructor
@NoArgsConstructor
@Builder
@Data
public class BoardInput {
private Long boardType;
private String title;
private String contents;
}
- BoardService.java
package com.example.jpa.sample.board.service;
import com.example.jpa.sample.board.entity.Board;
import com.example.jpa.sample.board.entity.BoardBadReport;
import com.example.jpa.sample.board.entity.BoardComment;
import com.example.jpa.sample.board.entity.BoardType;
import com.example.jpa.sample.board.model.*;
import java.util.List;
public interface BoardService {
...
ServiceResult add(String email, BoardInput boardInput);
}
- BoardServiceImpl.java
package com.example.jpa.sample.board.service;
import com.example.jpa.sample.board.entity.*;
import com.example.jpa.sample.board.model.*;
import com.example.jpa.sample.board.repository.*;
import com.example.jpa.sample.common.exception.BizException;
import com.example.jpa.sample.user.entity.User;
import com.example.jpa.sample.user.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
@RequiredArgsConstructor
@Service
public class BoardServiceImpl implements BoardService {
...
@Override
public ServiceResult add(String email, BoardInput boardInput) {
Optional<User> optionalUser = userRepository.findByEmail(email);
if(!optionalUser.isPresent()) {
throw new BizException("회원 정보가 존재하지 않습니다.");
}
User user = optionalUser.get();
Optional<BoardType> optionalBoardType = boardTypeRepository.findById(boardInput.getBoardType());
if(!optionalBoardType.isPresent()) {
return ServiceResult.fail("게시판 정보가 존재하지 않습니다.");
}
BoardType boardType = optionalBoardType.get();
Board board = Board.builder()
.user(user)
.boardType(boardType)
.title(boardInput.getTitle())
.contents(boardInput.getContents())
.regDate(LocalDateTime.now())
.build();
boardRepository.save(board);
return ServiceResult.success();
}
}
- ApiBoardController.java
package com.example.jpa.sample.board.controller;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.example.jpa.sample.board.entity.Board;
import com.example.jpa.sample.board.entity.BoardType;
import com.example.jpa.sample.board.model.*;
import com.example.jpa.sample.board.service.BoardService;
import com.example.jpa.sample.common.exception.BizException;
import com.example.jpa.sample.common.model.ResponseResult;
import com.example.jpa.sample.notice.model.ResponseError;
import com.example.jpa.sample.user.model.ResponseMessage;
import com.example.jpa.sample.util.JwtUtils;
import lombok.RequiredArgsConstructor;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
@RequiredArgsConstructor
@RestController
public class ApiBoardController {
...
//------------------------------------------------------------------------------
// 문제 1
@GetMapping("/api/board")
public ResponseEntity<?> list() {
List<Board> list = boardService.list();
return ResponseResult.success(list);
}
// 문제 2
@PostMapping("/api/board")
public ResponseEntity<?> add(@RequestBody BoardInput boardInput, @RequestHeader("X-ACCESS-TOKEN") String token) {
// String email = "";
// try {
// email = JwtUtils.getIssuer(token);
// } catch(JWTVerificationException e) {
// return ResponseResult.fail("토큰 정보가 정확하지 않습니다.");
// }
String email = JwtUtils.getIssuer(token); // 인터셉터에서 자동으로 예외를 잡음
ServiceResult result = boardService.add(email, boardInput);
return ResponseResult.success(result);
}
}
- CommonInterceptor.java
package com.example.jpa.sample.common.interceptor;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.example.jpa.sample.common.exception.AuthFailException;
import com.example.jpa.sample.util.JwtUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Slf4j
public class CommonInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
log.info("#################################");
log.info("[인터셉터] - preHandler 시작");
// 요청한 Method, URI 정보
log.info(request.getMethod());
log.info(request.getRequestURI());
if(!!validJWT(request)) {
throw new AuthFailException("인증 정보가 정확하지 않습니다.");
}
return true;
}
private boolean validJWT(HttpServletRequest request) {
String token = request.getHeader("X-ACCESS-TOKEN");
String email = "";
try {
email = JwtUtils.getIssuer(token);
} catch(JWTVerificationException e) {
return false;
}
// request.setAttribute("email", email); 로 데이터를 전달 할 수 있음
return true;
}
}
- AuthFailException.java
package com.example.jpa.sample.common.exception;
public class AuthFailException extends RuntimeException {
public AuthFailException(String message) {
super(message);
}
}
- GlobalExceptionHandler.java
package com.example.jpa.sample.common.handler;
import com.example.jpa.sample.common.exception.AuthFailException;
import com.example.jpa.sample.common.model.ResponseResult;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
@RestControllerAdvice
public class GlobalExceptionHandler {
@ExceptionHandler(AuthFailException.class)
public ResponseEntity<?> AuthFailException(AuthFailException exception) {
return ResponseResult.fail("[인증 실패]" + exception.getMessage());
}
}
728x90
'Spring > Practice' 카테고리의 다른 글
[Practice] 메일 전송 (1) (0) | 2021.04.20 |
---|---|
[Practice] Open API 연동 시 API 프로퍼티 활용 (0) | 2021.04.20 |
[Practice] 인터셉터 활용 (1) (0) | 2021.04.19 |
[Practice] 사용자 관련 API 만들기 (8) (0) | 2021.04.19 |