인터셉터(Interceptor)는 스프링 MVC에서 제공하는 기능으로, 클라이언트의 요청을 처리하는 과정에서 특정 작업을 수행할 수 있도록 도와준다. 인터셉터는 컨트롤러의 메서드(URI)에 접근하는 과정에서 요청을 가로채어 전처리(pre-processing) 및 후처리(post-processing)를 할 수 있다.
필터(Filter)와의 차이점
- 필터는 서블릿 레벨에서 동작하며, 모든 요청에 대해 작동한다.
- 인터셉터는 스프링 MVC 레벨에서 동작하며, 특정 핸들러(컨트롤러)로의 요청에만 작동한다.
인터셉터를 통해 로그인 여부 확인, 권한 검사, 로깅, 요청 시간 측정 등 다양한 작업을 효율적으로 처리할 수 있다.
로그인 인터셉터 만들기
로그인 인터셉터는 사용자의 로그인 상태를 확인하고, 로그인하지 않은 사용자가 보호된 리소스에 접근하려 할 때 적절한 조치를 취하는 역할을 한다.
LoginInterceptor
package com.tenco.blog_v2.common.config;
import com.tenco.blog_v2.common.errors.Exception401;
import com.tenco.blog_v2.user.User;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
// IoC 를 안한 상태 이다.
public class LoginInterceptor implements HandlerInterceptor {
/**
* 컨트롤러 메서드 호출 전에 실행 되는 메서드 이다.
* @param request current HTTP request
* @param response current HTTP response
* @param handler chosen handler to execute, for type and/or instance evaluation
* @return
* @throws Exception
*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
System.out.println("LoginInterceptor preHandle 실행");
// 로그인 여부 판단
HttpSession session = request.getSession(false); // 기존 세션이 없다면 null 반환 한다.
if(session == null) {
throw new Exception401("로그인이 필요 합니다");
}
// 키 - 값 --> 세션 메모리지에 저장 방식은 map 구조 저장 (sessionUser) 문자열 사용 중
User sessionUser = (User) session.getAttribute("sessionUser");
if(sessionUser == null) {
throw new Exception401("로그인이 필요 합니다");
}
// return false <- 이면 컨트롤러로 들어가지 않는다.
return true;
}
/**
* 컨트롤러 실행 후, 뷰가 렌더링되기 전에 실행되는 메서드
*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
HandlerInterceptor.super.postHandle(request, response, handler, modelAndView);
}
/**
* 뷰가 렌더링 된 후 실행되는 메서드
*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
HandlerInterceptor.super.afterCompletion(request, response, handler, ex);
}
}
로그인 인터셉터 등록 하기
작성한 인터셉터를 스프링 부트 애플리케이션에 등록하고, 적용할 URL 패턴을 설정한다.
WebConfig
package com.tenco.blog_v2.common.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;
// @Component // IOC
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Autowired // DI 처리
private LoginInterceptor loginInterceptor;
/**
* 인터셉터를 등록하고 적용할 URL 패턴을 설정하는 메서드이다.
* @param registry
*/
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(loginInterceptor)
.addPathPatterns("/protected/**") // 인터셉터를 적용할 경로 패턴 설정
.excludePathPatterns("/public/**", "/login", "/logout"); // 인터셉터를 제외할 경로 패턴 설정
}
}
하지만 LoginInterceptor 아직 빈 등록 처리가 안되어 있다.
LoginInterceptor 빈으로 등록 처리
package com.tenco.blog_v2.common.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class InterceptorConfig {
@Bean // 빈으로 등록 처리 : 로그인 인터셉터를 빈으로 등록
public LoginInterceptor loginInterceptor() {
return new LoginInterceptor();
}
//
//
//
//
}
- @Bean: 메서드가 반환하는 객체를 스프링의 빈으로 등록한다.
- LoginInterceptor: 앞서 작성한 로그인 인터셉터를 빈으로 등록하여 WebConfig에서 주입받을 수 있게 한다.
User 코드 추가 → private String role;
package com.tenco.blog_v2.user;
import com.tenco.blog_v2.board.Board;
import jakarta.persistence.*;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.CreationTimestamp;
import java.sql.Timestamp;
import java.util.List;
@NoArgsConstructor
@Data
@Entity
@Table(name = "user_tb")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(unique = true) // 유니크 제약 조건 설정
private String username;
private String password;
private String email;
// "USER", "ADMIN";
@Column(nullable = false)
private String role;
@CreationTimestamp // 엔티티 생성시 자동으로 현재 시간 입력
private Timestamp createdAt;
// 단방향, 양방향 매핑(mappedBy)
// @OneToMany(mappedBy = "user", fetch = FetchType.LAZY) // 지연 로딩 설정
@OneToMany(mappedBy = "user", fetch = FetchType.LAZY) // 즉시 로딩 설정
private List<Board> boards;
@Builder
public User(Integer id, String username, String password, String email, Timestamp createdAt, List<Board> boards) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.createdAt = createdAt;
this.boards = boards;
}
}
-- 사용자 데이터 삽입
INSERT INTO user_tb(username, password, email, role, created_at) VALUES('길동', '1234', 'a@nate.com', 'USER', NOW());
INSERT INTO user_tb(username, password, email, role, created_at) VALUES('둘리', '1234', 'b@nate.com', 'USER', NOW());
INSERT INTO user_tb(username, password, email, role, created_at) VALUES('마이콜', '1234', 'c@nate.com', 'ADMIN', NOW());
-- 게시글 데이터 삽입
INSERT INTO board_tb(title, content, user_id, created_at) VALUES('제목1', '내용1', 1, NOW());
INSERT INTO board_tb(title, content, user_id, created_at) VALUES('제목2', '내용2', 1, NOW());
INSERT INTO board_tb(title, content, user_id, created_at) VALUES('제목3', '내용3', 2, NOW());
INSERT INTO board_tb(title, content, user_id, created_at) VALUES('제목4', '내용4', 3, NOW());
인터셉터를 이용한 권한 관리
인터셉터를 활용하여 특정 권한을 가진 사용자만 접근할 수 있도록 설정할 수 있다. 예를 들어, 관리자 권한을 가진 사용자만 접근할 수 있는 경로를 설정할 수 있다.
728x90
'Spring boot > Blog 프로젝트 만들기(JPA)' 카테고리의 다른 글
완성 코드 STEP 03 - 에러 컨트롤러 및 커스텀 익셉션 만들기 ( 인증과 권한 처리 ) (0) | 2024.10.11 |
---|---|
완성 코드 STEP 03 - 에러 페이지 만들기 ( 인증과 권한 처리 ) (0) | 2024.10.11 |
완성 코드 STEP 02 - 회원정보 수정 ( JPA API , JPQL 쿼리 사용, 인증(세션 로직 추가 ) (0) | 2024.10.10 |
완성 코드 STEP 02 - 회원 가입 ( JPA API , JPQL 쿼리 사용, 인증(세션 로직 추가 ) (0) | 2024.10.10 |
완성 코드 STEP 02 - 게시글 수정 ( JPA API , JPQL 쿼리 사용, 인증(세션 로직 추가 ) (0) | 2024.10.10 |