질문, 피드백 등 모든 댓글 환영합니다.
스프링 인터셉터를 활용하여 자신의 게시글, 댓글 수정/삭제 로직에 접근을 막는 기능을 개발합니다. 요청을 보낸 회원의 id와 요청에 포함된 엔티티의 member_id 와 비교하여 같을 경우에만 컨트롤러가 요청을 받을 수 있도록 개발하겠습니다.
Configurer
@Configuration
@RequiredArgsConstructor
public class Configurer implements WebMvcConfigurer {
private final PostService postService;
private final CommentService commentService;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new PostInterceptor(postService))
.order(1)
.excludePathPatterns("/post/add")
.addPathPatterns("/post/edit/*", "/post/*");
registry.addInterceptor(new CommentInterceptor(commentService))
.order(2)
.addPathPatterns("/post/*/comment/edit/*", "/post/*/comment/*");
}
}
인터셉터를 등록하고 적용될 URL을 지정합니다.
PostInterceptor
@RequiredArgsConstructor
public class PostInterceptor implements HandlerInterceptor {
private final PostService postService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
// 1.
String requestURI = request.getRequestURI();
// 2.
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetailsImpl userDetails = (UserDetailsImpl) principal;
Member loginMember = userDetails.getMember();
// 3.
int pos = requestURI.lastIndexOf("/");
Long postId = Long.parseLong(requestURI.substring(pos + 1));
// 4.
HandlerMethod method = (HandlerMethod) handler;
if (method.getMethod().getName().equals("post")) return true;
// 5.
Post post = postService.findPostForInterceptor(postId);
if (!post.getMember().getId().equals(loginMember.getId())) {
response.sendRedirect("/post");
return false;
}
return true;
}
}
전체적인 로직은 1. 요청 URI 조회 2. 로그인 Member 조회 3. {post_id} 매핑 4. 이후 호출되는 메서드 조회 5. id 검증 후 반환 으로 이루어집니다.
HanlderInterceptor는 파라미터로 Object handler
를 제공합니다. 이 필드를 이용하여 호출되는 컨트롤러와 메서드의 정보에 접근할 수 있습니다.
PostInterceptor에선 호출 메서드의 이름이 "post"
일 경우에는 true를 반환합니다. (post()
는 단순 조회 로직이라 id 검증 불필요)
이후 Post의 memberId와 loginMember.getId()를 비교하여 다를 경우 false를 반환하고 "/post"
로 리다이렉트 시켜주었습니다.
CommentInterceptor
@RequiredArgsConstructor
public class CommentInterceptor implements HandlerInterceptor {
private final CommentService commentService;
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String requestURI = request.getRequestURI();
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetailsImpl userDetails = (UserDetailsImpl) principal;
Member loginMember = userDetails.getMember();
int pos = requestURI.lastIndexOf("/");
Long comment_id = Long.parseLong(requestURI.substring(pos + 1));
Comment comment = commentService.findCommentForInterceptor(comment_id);
if (!comment.getMember().getId().equals(loginMember.getId())) {
response.sendRedirect("/post");
return false;
}
return true;
}
}
PostInterceptor
와 거의 동일하고 Objcet handler
를 통한 메서드 조회 로직이 빠졌습니다.
지금까지 작성했던 코드는 몇가지 문제가 있습니다. 처음에 언급했었던 commentNum, heartNum 컬럼에 관한 문제와 엔티티를 삭제할 때 CascadeType.REMOVE
때문에 발생하는 문제 등이 있는데 이를 개선하겠습니다.