ㅁ 스프링 프로젝트에서 로그인 체크 인터셉터 클래스를 복사해서 붙여넣기 한다.
- 패키지선언부를 수정한다.
- import보면 javax로 되어있다. 스프링 때는 톰캣 9버전이어서 javax 패키지에서 import 했었다.
지금 쓰는 스프링 부트 버전(3.2.11)은 톰캣 10버전이어서 jakarata 패키지에서 import 해야 한다.
- ctrl shift o로 다시 import 한다.
ㅁ(스프링) servlet-context.xml
<?xml version="1.0" encoding="UTF-8"?>
<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
<!-- Enables the Spring MVC @Controller programming model -->
<annotation-driven />
<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
<resources mapping="/resources/**" location="/resources/" />
<resources mapping="/upload/**" location="file:///upload/" />
<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<beans:property name="prefix" value="/WEB-INF/views/" />
<beans:property name="suffix" value=".jsp" />
</beans:bean>
<context:component-scan base-package="com.br.spring" />
<!-- webSocket 관련 등록 구문 -->
<beans:bean class="com.br.spring.handler.ChatEchoHandler" id="chatEchoHandler" />
<websocket:handlers>
<websocket:mapping handler="chatEchoHandler" path="/chat" />
<websocket:handshake-interceptors>
<beans:bean class="org.springframework.web.socket.server.support.HttpSessionHandshakeInterceptor" />
</websocket:handshake-interceptors>
<websocket:sockjs />
</websocket:handlers>
<!-- interceptor 관련 등록 구문 -->
<interceptors>
<interceptor>
<mapping path="/member/myinfo.do" />
<mapping path="/board/regist.do" />
<beans:bean class="com.br.spring.interceptor.LoginCheckInterceptor" id="LoginCheckInterceptor"/>
</interceptor>
<!--
<interceptor>
</interceptor>
-->
</interceptors>
<!-- Scheduler -->
<task:annotation-driven />
</beans:beans>
ㅁ LoginCheckInterceptor
package com.br.boot.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.support.RequestContextUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@Component // servlet-context.xml 대체
public class LoginCheckInterceptor implements HandlerInterceptor{
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession();
if(session.getAttribute("loginUser") != null) { // 로그인이 되어있을 경우
return true; // 정상적으로 컨트롤러 실행
}else { // 로그인이 되어있지 않을 경우
// alert 메세지와 함께 메인페이지가 다시 보여지도록
// RedirectAttributes의 대안
FlashMap flashMap = new FlashMap(); // Map같은거라 키-밸류 세트로 무언가를 담을 수 있다.
flashMap.put("alertMsg", "로그인 후 이용가능한 서비스입니다.");
// RequestContextUtils.getFlashMapManager(request) 여기까지가 FlashMapManager 객체를 반환한다.
RequestContextUtils.getFlashMapManager(request).saveOutputFlashMap(flashMap, request, response);
response.sendRedirect(request.getContextPath());
return false; // 컨트롤러 실행되지 않도록
}
}
}
- 빈등록을 해야 한다. 빈등록은 3가지 방식이 있다.
- LoginCheckInterceptor 클래스 상단에 @Component를 붙여서 빈등록을 한다.
ㅁ WebMvcConfig
package com.br.boot.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import com.br.boot.interceptor.LoginCheckInterceptor;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
private final LoginCheckInterceptor loginCheckInterceptor;
// 리소스 핸들링 등록을 할 수 있는 메소드 (servlet-context.xml의 <resources> 태그 설정 대신)
public void addResourceHandlers(ResourceHandlerRegistry registry) {
// <resources mapping="/resources/**" location="classpath:/static/" />
registry.addResourceHandler("/resources/**")
.addResourceLocations("classpath:/static/");
registry.addResourceHandler("/upload/**")
.addResourceLocations("file:///upload/");
}
public void addInterceptors(InterceptorRegistry registry) {
/*
<interceptor>
<mapping path="/member/myinfo.do" />
<mapping path="/board/regist.do" />
<beans:bean class="com.br.spring.interceptor.LoginCheckInterceptor" id="LoginCheckInterceptor"/>
</interceptor>
*/
registry.addInterceptor(loginCheckInterceptor)
.addPathPatterns("/member/myinfo.do")
.addPathPatterns("/board/regist.do");
// 다른 인터셉터도 등록하고 싶다면 위의 3줄을 또 쓰면 됨.
}
}
- ctrl을 누른채로 클릭해서 implements한 WebMvcConfigurer를 가서 addInterceptors 메소드를 가져온다.
- 접근제한자를 default에서 public으로 바꾼다.
- 여러 인터셉터를 등록할 수 있다.
ㅁ 서버 start
- 로그인 되지 않은채로 http://localhost:8888/board/regist.do를 요청하면 메인이 떠야하는데 whitelabel error page가 뜬다.
- 그리고 변경된 url을 확인해보면 /board/까지 그어져있다.
인터셉터가 제대로 동작했다면 localhost:8888이 요청되면서 메인페이지가 떠야 한다.
ㅁ LoginCheckInterceptor 수정
package com.br.boot.interceptor;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.support.RequestContextUtils;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import jakarta.servlet.http.HttpSession;
@Component // servlet-context.xml 대체
public class LoginCheckInterceptor implements HandlerInterceptor{
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
HttpSession session = request.getSession();
if(session.getAttribute("loginUser") != null) { // 로그인이 되어있을 경우
return true; // 정상적으로 컨트롤러 실행
}else { // 로그인이 되어있지 않을 경우
// alert 메세지와 함께 메인페이지가 다시 보여지도록
// RedirectAttributes의 대안
FlashMap flashMap = new FlashMap(); // Map같은거라 키-밸류 세트로 무언가를 담을 수 있다.
flashMap.put("alertMsg", "로그인 후 이용가능한 서비스입니다.");
// RequestContextUtils.getFlashMapManager(request) 여기까지가 FlashMapManager 객체를 반환한다.
RequestContextUtils.getFlashMapManager(request).saveOutputFlashMap(flashMap, request, response);
response.sendRedirect( request.getContextPath().equals("") ? "/" : request.getContextPath() );
// case 1) contextPath가 ""일 경우
// localhost:8888/member/myinfo.do url 요청시 로그인되어있지 않을 경우 "" url 재요청 된다.
// localhost:8888/member/ url 재요청 된다.
// case 2) contextPath가 "/boot"일 경우
// localhost:8888/boot/member/myinfo.do url 요청시 로그인되어있지 않을 경우 "/boot" url이 재요청 된다.
// localhost:8888/boot url 재요청 된다.
return false; // 컨트롤러 실행되지 않도록
}
}
}
- sndRedirect보면 우리의 컨텍스트패스를 요청하게 되어있다.
근데 컨텍스트패스가 지금 빈문자열로 되어 있다.
- application.properti에서 컨텍스트패스 등록구문을 주석처리안했다면 발생하지 않았을 문제다.
- respopnse.sendRedirect() 부터 return false 이전까지 작성했음.
ㅁ 서버 start
- 서버 스타트 후 아까와 같이 로그인하지 않고 http://localhost:8888/board/regist.do를 요청하면 alert가 뜨고 메인페이지로 이동된다.