스프링부트(Spring Boot) MyBatis 게시판 만들기3 - Interceptor 처리 [Mysql, DBeaver, IntelliJ, Maven]

예림·2024년 6월 7일
2
post-thumbnail

저번 포스팅에 이어 이번에는 로그인을 한 사용자만 글을 열람할 수 있도록 Interceptor를 적용했다.

권한이 없는(로그인하지 않은) 상태로 게시물 상세페이지(/board/{bno}) 접근 시, Interceptor가 요청을 빼앗아 /login페이지로 redirect한다.

인터셉터 적용


개발 환경

  • 언어: java
  • Spring Boot ver : 2.3.1.RELEASE
  • Mybatis : 2.3.0
  • IDE: intelliJ
  • SDK: JDK 17
  • 의존성 관리툴: Maven
  • DB: MySQL 8.0.12

UserController.java → 컨트롤러

@GetMapping("/login")
public String loginForm(Model model) {

        model.addAttribute("loginForm", new LoginForm());
        return "login";
}

@PostMapping("/login")
public String login(@ModelAttribute("loginForm") LoginForm form, BindingResult bindingResult, HttpServletResponse response) {

        User loginUser = service.login(form.getLoginId(), form.getPassword());
        log.info("login? {}", loginUser);

        if (loginUser == null) {
            bindingResult.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
        }

        if (bindingResult.hasErrors()) {
            return "login";
        }

        Cookie cookie = new Cookie("idx", String.valueOf(loginUser.getIdx()));
        cookie.setMaxAge(60 * 60);  // 쿠키 유효 시간 : 1시간
        response.addCookie(cookie);

        // 로그인 성공 처리
        return "redirect:/main";
}

@GetMapping("/user/main")
public String userList(Model model) {
        List<User> users = service.getAllUsers();
        model.addAttribute("users", users);
        return "user/main";
}

@GetMapping("/user/info/{userId}")
public String userInfo(@PathVariable String userId, Model model) {
        log.info("Fetching user info for userId: {}", userId);
        User user = service.getLoginUser(userId);
        if (user == null) {
            log.warn("User not found for userId: {}", userId);
            return "redirect:/login";
        }
        log.info("User found: {}", user);
        model.addAttribute("user", user);
        return "user/info";
}

AuthInterceptor.java → 인터셉터 구현(Cookie)

package org.study.board.config;

import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.Arrays;
import java.util.Optional;

@Component
public class AuthInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(final HttpServletRequest request, final HttpServletResponse response,Object handler) throws Exception {

        // Cookie 방식
        // 쿠키에서 사용자 토큰을 찾습니다.
        Optional<Cookie> userTokenCookie = Arrays.stream(request.getCookies())
                .filter(cookie -> cookie.getName().equals("idx"))
                .findFirst();

        // 사용자 토큰이 존재하지 않으면 로그인 페이지로 리다이렉트합니다.
        if (!userTokenCookie.isPresent()) {
            response.sendRedirect("/login");
            return false;
        }

        // 토큰이 존재하면 인증을 성공한 것으로 간주합니다.
        return true;
    }
}

WebMvcConfig.java → 인터셉터 적용

package org.study.board.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;

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
    @Autowired
    private AuthInterceptor sessionInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 명시하는 요청 설계 주소에서만 동작하도록

        // localhost:8080/hello <-- 동작x
        // localhost:8080/user/info/{userId} <-- 인터셉터 동작
        registry.addInterceptor(sessionInterceptor)
                .addPathPatterns("/board/**"); // board 아래에 있는것만 가로챔
    }
}
  1. 인터셉터를 빈으로 등록
  2. WebMvcConfigurer의 addInterceptors() 메서드로 인터셉터 설정2-1. InterceptorRegister 객체의 addInterceptor() 메서드로 등록한 인터셉터를 설정2-2. InterceptorRegister 객체의 addPathPatterns("ant 패턴")으로 인터셉트할 url 설정

실행 화면


  • /board/{bno} 요청

    1. 로그아웃 상태이면 → Interceptor가 권한 빼앗음

    • /login 로그인 페이지로 리다이렉트

    1. 로그인 상태이면

    • /board/{bno} 글 상세 페이지로 정상 응답

profile
백엔드 개발하는 사람

0개의 댓글