저번 포스팅에 이어 이번에는 로그인을 한 사용자만 글을 열람할 수 있도록 Interceptor를 적용했다.
권한이 없는(로그인하지 않은) 상태로 게시물 상세페이지(/board/{bno}) 접근 시, Interceptor가 요청을 빼앗아 /login페이지로 redirect한다.
개발 환경
2.3.1.RELEASE
2.3.0
8.0.12
@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";
}
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;
}
}
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 아래에 있는것만 가로챔
}
}
WebMvcConfigurer
의 addInterceptors()
메서드로 인터셉터 설정2-1. InterceptorRegister
객체의 addInterceptor()
메서드로 등록한 인터셉터를 설정2-2. InterceptorRegister
객체의 addPathPatterns("ant 패턴")
으로 인터셉트할 url 설정/board/{bno}
요청
로그아웃 상태이면 → Interceptor가 권한 빼앗음
/login
로그인 페이지로 리다이렉트
로그인 상태이면
/board/{bno}
글 상세 페이지로 정상 응답