Spring Login#2 ํํฐ, ์ธํฐ์ ํฐ, ArugmentResolver
by JiwonDev2021.08.29 - [Backend/Spring MVC] - Spring Login#1 ์ฟ ํค์ ์ธ์
Spring Login#1 ์ฟ ํค์ ์ธ์
๋ก๊ทธ์ธ (LoginForm.html)์์ ID,PW๋ฅผ ๋ฐ์์ ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด ์ฟ ํค๋ฅผ ์ ์กํ๋ ๋ฐฉ๋ฒ์ผ๋ก ๊ตฌํํด๋ณด์. ์ฟ ํค๋ฅผ ์ ์กํ๋ ๊ณผ์ ์ ๋งค์ฐ ๊ฐ๋จํ๋ค. ํต์ฌ์ ์ฟ ํค๋ฅผ ์ด์ฉํด์ '์ด๋ป๊ฒ ๋ก๊ทธ์ธ ์ํ๋ฅผ ์ ์ง
jiwondev.tistory.com
# ์๋ธ๋ฆฟ ํํฐ์ ๊ณตํต๊ด์ฌ์ฌํญ
์์์ ๋ง๋ ๋ก๊ทธ์ธ ์์ ๋ 'ํ ํ๋ฉด'๋ง ๋ก๊ทธ์ธ ์ํ์ ๋ฐ๋ผ ๋ค๋ฅธ ํ์ด์ง๋ฅผ ๋ณด์ฌ์คฌ์๋ค. ํ์ง๋ง ์ค์ ์๋น์ค์์๋ ๋ชจ๋ ํ์ด์ง์์ ๋ก๊ทธ์ธ์ด ์ ์ง๋์ด์ผํ๋ค. โก ์ธ์ ์ ์ฌ์ฉํ๋ ์ฝ๋๋ฅผ ๋ชจ๋ ์ปจํธ๋กค๋ฌ์ ์ ์ฉ์์ผ์ผํ๋ค.
- ์ด๋ ๊ฒ ๋ชจ๋ ๊ณณ์ ์ ์ฉ๋๋ '๊ณตํต ๊ด์ฌ์ฌํญ' ๋ก์ง์ ๋ถ๋ฆฌํ๊ธฐ ์ํด์ ์๋ธ๋ฆฟ์์๋ ํํฐ ๊ธฐ๋ฅ์ ์ ๊ณตํ๋ค.
2021.07.18 - [Backend/Java] - #17 Servlet Filter
// Filter ์ธํฐํ์ด์ค๋ Servlet๊ณผ ๋น์ทํ๊ฒ ์ฌ์ฉํ ์ ์๋ค.
package javax.servlet;
import java.io.IOException;
public interface Filter {
// ์ฑ๊ธํด์ ๊ตฌํํ์ง๋ ์์ผ๋, ๋ณดํต 1๊ฐ์ ๊ฐ์ฒด๋ง์ ์์ฑํด์ ์ฌ์ฉํ๋ค.
// ์ํ๋ค๋ฉด web.xml์ ์ค์ ์ ๋ฐ๋ผ ์ฌ๋ฌ๊ฐ์ ์ธ์คํด์ค๋ฅผ ๊ฐ์ง ์๋ ์๋ค.
public void init(FilterConfig filterConfig) throws ServletException;
// ํด๋ผ์ด์ธํธ์ ์์ฒญ์ด ๋ค์ด์ค๋ฉด, ์์ฒญ/์๋ต์ ์กฐ์ํ๊ณ
// FilterChain์ ์ด์ฉํด ์กฐ์ ์ดํ ์๋ ๋ชฉ์ ์ง์ธ ์๋ธ๋ฆฟ์ผ๋ก ์ ๋ฌํ๋ค.
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
public void destroy();
}
์๋ธ๋ฆฟ์ ํํฐ๋ฅผ ์คํ๋ง์ AOP๋ก ์ง์ ๋ง๋ค ์ ์๊ฒ ์ง๋ง, AOP๋ ์น๊ณผ ๊ด๋ จ๋ ๋๊ตฌ๊ฐ ์๋๋ผ์ ์ฌ์ฉํ๊ธฐ ๋ถํธํ๋ค. ๊ทธ๋์ ์คํ๋ง ์ธํฐ์ ํฐ๋ฅผ ๋ฐ๋ก ์ ๊ณตํ๋ค. ์ธํฐ์ ํฐ๋ ์๋ธ๋ฆฟ ํํฐ์ ๋ง์ฐฌ๊ฐ์ง๋ก HttpServletRequest๋ฅผ ์ฌ์ฉํ ์ ์๊ฒ ๋ง๋ค์ด์ค๋ค.
์ฐธ๊ณ ๋ก HTTP ์์ฒญ ๋ก๊ทธ์ ์ธ์ ID๋ฅผ ํจ๊ป ๋จ๊ธฐ๊ณ ์ถ๋ค๋ฉด [ํํฐ, ์ธํฐ์ ํฐ] ๋์ ์ logback mdc๋ฅผ ์ฌ์ฉํ ์ ์๋ค.
# ์๋ธ๋ฆฟ ํํฐ๋ฅผ ์ด์ฉํ ์ธ์ ์ ์ง
๊ณผ๊ฑฐ์๋ ์๋ธ๋ฆฟ ํํฐ๋ฅผ ์ด์ฉํด์ ์ธ์ ์ ์ง๋ผ๋ ๊ณตํต ๊ด์ฌ์ฌํญ์ ์ ์ฉ์์ผฐ์๋ค.
์ฌ์ฉ๋ฒ์ ํด๋น ๋งํฌ์ ์์ธํ ๋ค๋ฃจ๊ณ ์์ผ๋ฏ๋ก ์๋ตํ๋๋ก ํ๊ฒ ๋ค. ์๋์ ์์ ์ฒ๋ผ ์ฐ๋ฉด ๋๋ค.
@WebServlet(name = "loadAppConfig", urlPatterns = { "/loadConfig" }, loadOnStartup = 1)
public class LoggingFilter implements Filter {
// ํํฐ ๊ฐ์ฒด๊ฐ ์์ฑ๋ ๋ ์ด๊ธฐํ์ ์ฌ์ฉ
// config ๊ฐ์ฒด์์ ํํฐ ์ ๋ณด, ์ฃผ์ด์ง ํ๋ผ๋ฉํ, ์๋ธ๋ฆฟ ์ ๋ณด๋ฑ๋ฅผ ์ป์ ์ ์๋ค.
public void init(FilterConfig config) throws ServletException {
System.out.println("ํํฐ ์ด๊ธฐํ ๋จ");
}
//์์ฒญ์๋ง๋ค ํํฐ๊ฐ ์คํํ ๋ฉ์๋
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
System.out.println("์์ฒญ์ด ํํฐ์์ ์ฒ๋ฆฌ๋จ");
chain.doFilter(request, response); // ์กฐ์์ ์๋ฃํ ์์ฒญ/์๋ต์ ๋ฐํ.
System.out.println("์๋ต์ด ํํฐ์์ ์ฒ๋ฆฌ๋จ");
}
//ํํฐ ๊ฐ์ฒด๊ฐ ์ ๊ฑฐ๋ ๋ ์คํ
public void destroy() {
System.out.println("ํํฐ ์ ๊ฑฐ๋จ.");
}
}
๋ง์ฝ ์๋ธ๋ฆฟ ํํฐ๋ฅผ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋กํด ์ฌ์ฉํ๊ณ ์ถ๋ค๋ฉด, ์๋์ ๊ฐ์ด ์ด๊ธฐํ ํ ์ ์๋ค.
// ์ปดํฌ๋ํธ ์๋์ค์บ์ ํ๋ ๋ฐฉ๋ฒ
@ServletComponentScan
@WebServlet(name = "loadAppConfig", urlPatterns = { "/*" }, loadOnStartup = 1)
public Class LogFilter{ ... }
// FilterRegistrationBean ๋ฅผ ์ด์ฉํด์ ์๋์ผ๋ก ๋ฑ๋กํ๋ ๋ฐฉ๋ฒ
// ๋ฌผ๋ก ํํฐ ๊ฐ์ฒด๋ฅผ ๊ทธ๋๋ก ๋ฑ๋กํด๋ ์๊ด์์ง๋ง, ์ฌ์ฉํ๋ฉด ๋ค์ํ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋ค.
import org.springframework.boot.web.servlet.FilterRegistrationBean;
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean logFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LogFilter());
filterRegistrationBean.setOrder(1); // ํํฐ์์๋ ์๋๋ ์ฒด์ธ ์์ ์ง์ ๋ ๊ฐ๋ฅ
filterRegistrationBean.addUrlPatterns("/*"); // ํํฐ๋ฅผ ์ ์ฉํ URL ๊ท์น ์ถ๊ฐ
return filterRegistrationBean;
}
}
์ด๋ ๊ฒ ์ฌ์ฉํ ์ผ์ ์๊ฒ ์ง๋ง, ์คํ๋ง์์ ํํฐ๋ฅผ ์ด๋ค๋ฉด ์๋์ ๊ฐ์ด ๊ตฌํํ๋ฉด ๋๋ค.
๐ LoginCheckFilter
@Slf4j
public class LoginCheckFilter implements Filter {
// ๋ก๊ทธ์ธ์ด ํ์์๋ URL ๋ชจ์ (whiteList)
private static final String[] whitelist = {"/", "/members/add", "/login", "/logout", "/css/*"};
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
HttpServletResponse httpResponse = (HttpServletResponse) response;
try {
log.info("์ธ์ฆ ์ฒดํฌ ํํฐ ์์ {}", requestURI);
if (isLoginWhitelistPath(requestURI)) { // ๋ก๊ทธ์ธ์ด ํ์ํ ํ์ด์ง ์ ์
HttpSession session = httpRequest.getSession(false);
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
// ๋ฏธ์ธ์ฆ ์ฌ์ฉ์ ์์ฒญ -> ๋ก๊ทธ์ธ์ผ๋ก redirect
httpResponse.sendRedirect("/login?redirectURL=" + requestURI);
return;
}
}
chain.doFilter(request, response);
} catch (Exception e) {
throw e; //์์ธ์ฒ๋ฆฌ & ๋ก๊น
๊ฐ๋ฅํ์ง๋ง, ํฐ์บฃ๊น์ง ์์ธ๋ฅผ ๋ณด๋ด์ฃผ์ด์ผ ํจ
} finally {
log.info("์ธ์ฆ ์ฒดํฌ ํํฐ ์ข
๋ฃ {} ", requestURI);
}
}
// ํ์ดํธ ๋ฆฌ์คํธ URL์ ๊ฒฝ์ฐ ์ธ์ฆ ์ฒดํฌX
private boolean isLoginWhitelistPath(String requestURI) {
// ์คํ๋ง์ PatternMatchUtils๋ฅผ ์ฌ์ฉ. ์ด๋ฅผ ์ง์ ๊ตฌํํ๋ฉด ์ฝ๋๊ฐ ๋งค์ฐ ๋ณต์กํด์ง๋ค.
return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
}
}
๊ทธ๋ฆฌ๊ณ ํํฐ์์ Request์ ๋ฆฌ๋ค์ด๋ ํธํ URL์ ์ถ๊ฐํด์ฃผ๋ฉด ์๋์ ๊ฐ์ด ๋ง๋ค ์ ์๋ค.
- ๋ก๊ทธ์ธ์ ์ฑ๊ณตํ๋ฉด ํ ํ๋ฉด์ผ๋ก ๋ณด๋ด๋๊ฒ ์๋๋ผ, ๊ธฐ์กด์ ๋ณด๋ URL๋ก ๋ณด๋ด์ค๋ค.
@PostMapping("/login")
public String loginV4(@Valid @ModelAttribute LoginForm form, BindingResult bindingResult,
@RequestParam(defaultValue = "/") String redirectURL, // redirectURL์ ํํฐ์์ ๋ฐ์์ด
HttpServletRequest request) {
// ... ๊ธฐ์กด ์ฝ๋์ ๋์ผ ... //
return "redirect:" + redirectURL;
}
# ์คํ๋ง ์ธํฐ์ ํฐ๋?
์๋ธ๋ฆฟ์ ์๋ฐ ์น ํ์ค์์ ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ด๋ผ๋ฉด, ์ธํฐ์ ํฐ๋ ์คํ๋ง MVC์์๋ง ์ ๊ณตํ๋ ๊ธฐ๋ฅ์ด๋ค.
์คํ๋ง ์ธํฐ์ ํฐ๋ฅผ ์ฌ์ฉํ๋ ค๋ฉด HandlerInterceptor ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ฉด ๋๋ค.
public interface HandlerInterceptor {
// ์ปจํธ๋กค๋ฌ ์์ฒญ ์
default boolean preHandle(HttpServletRequest request, HttpServletResponse response,
Object handler) throws Exception {
}
// ์ปจํธ๋กค๋ฌ ํธ์ถ ์ดํ (๋ทฐ์ ์ ๋ฌํ Model ๊ฐ์ฒด ์ ๊ณต)
default void postHandle(HttpServletRequest request, HttpServletResponse response,
Object handler, @Nullable ModelAndView modelAndView)
throws Exception {
}
// ์์ ํ๊ฒ HTTP ์์ฒญ์ด ๋๋ ์ดํ (Exception ์ ๊ณต)
default void afterCompletion(HttpServletRequest request, HttpServletResponse response,
Object handler, @Nullable Exception ex) throws
Exception {
}
}
- preHandle ๋ ์ปจํธ๋กค๋ฌ์ ๊ฐ๊ธฐ์ ์ ํธ์ถ๋๋ ๋ฉ์๋์ด๋ค.
โก preHandle ๋ฐํ ๊ฐ์ด true ์ด๋ฉด ๋ค์ ์ธํฐ์ ํฐ๋ฅผ ํธ์ถํ๊ณ , false์ด๋ฉด ์ปจํธ๋กค๋ฌ๋ฅผ ๋ฐ๋ก ํธ์ถํ๋ค. - postHandle ๋ ์ปจํธ๋กค๋ฌ์ return ์ดํ ํธ์ถ๋๋ ๋ฉ์๋์ด๋ค.
โก ๋ทฐ์ ์ ๋ฌํ Model์ ์กฐ์ํ ์ ์๋ค. - afterCompletion ์ HTML ๋ทฐ๊ฐ ๋ ๋๋ง๋ ์ดํ ํธ์ถ๋๋ ๋ฉ์๋์ด๋ค.
- postHandle ๋ ์ปจํธ๋กค๋ฌ์ ์์ธ๊ฐ ๋ฐ์ํ๋ฉด ํธ์ถ๋์ง ์์ง๋ง afterCompletion์ ์์ธ์ ์๊ด์์ด ํญ์ ํธ์ถ๋๋ค.
# ์คํ๋ง ์ธํฐ์ ํฐ ๋ฑ๋ก๋ฐฉ๋ฒ
@ 1. ์ธํฐ์ ํฐ ๊ฐ์ฒด ๋ง๋ค๊ธฐ
์๋ธ๋ฆฟ ํํฐ์ ๋น์ทํ๊ฒ ์ฌ์ฉํ ์ ์๋ค. HandlerInterceptor ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๋ฉด ๋๋ค.
- ์ธํฐ์ ํฐ ๋ํ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก๋๋ค. ์ฆ ์ฑ๊ธํค์ด๋ฏ๋ก ํด๋์ค ๋ด์ ํ๋(์ํ๊ฐ)์ ์ฌ์ฉํด์๋ ์๋๋ค.
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
String requestURI = request.getRequestURI();
log.info("์ธ์ฆ ์ฒดํฌ ์ธํฐ์
ํฐ ์คํ {}", requestURI);
HttpSession session = request.getSession();
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
// ๋ฏธ์ธ์ฆ ์ฌ์ฉ์ ์์ฒญ -> ๋ก๊ทธ์ธ์ผ๋ก redirect
response.sendRedirect("/login?redirectURL=" + requestURI);
return false; // ์ปจํธ๋กค๋ฌ ์คํ
}
return true; // ๋ค์ ์ธํฐ์
ํฐ ์คํ
}
}
์ฐธ๊ณ ๋ก preHandle(... Object handler )๋ ์คํ๋งMVC๊ฐ ์ฌ์ฉํ๋ ํธ๋ค๋ฌ์ ๋ชจ๋ ์ ๋ณด๋ฅผ ๋ด๊ณ ์๋ค.
- HandlerMethod๋ก ์บ์คํ ํ๋ฉด ์ปจํธ๋กค๋ฌ ๋น ๊ฐ์ฒด์ RequestMapping ๋ฉ์๋ ์ ๋ณด๋ฅผ ์ป์ ์ ์๋ค.
- ResourceHttpRequestHandler๋ก ์บ์คํ ํ๋ฉด ์์ฒญ HTTP ํค๋์ ๊ฐ์ ์ ์ ๋ฆฌ์์ค ์ ๋ณด๋ฅผ ์ป์ ์ ์๋ค.
- Object handler๊ฐ ์ด๋ป๊ฒ ์์ฑ๋๊ฑด์ง ์ดํดํ๋ ค๋ฉด ์คํ๋ง MVC์ Dispatcher Servlet์ ๋์์ ์ดํดํ๋ฉด ๋๋ค.
โก Dispatcher Servlet ์์ URI ์์ฒญ์ ๋ง๋ ํธ๋ค๋ฌ๋ฅผ ์ฐพ๊ณ , ํธ๋ค๋ฌ ์ด๋ํฐ๋ก ์ปจํธ๋กค๋ฌ๋ฅผ ์คํํ๋ค.
โก (Object handler) ๋ ์ ํ๋ ์ปจํธ๋กค๋ฌ ๊ฐ์ฒด์ ์ปจํธ๋กค๋ฌ ๊ฐ์ฒด์ ์ ๋ฌํ HTTP ์์ฒญ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ง๊ณ ์๋ค.
// Dispatcher Servlet์ ์๋น์ค ๋ฉ์๋
@Override
protected void service(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
Object handler = getHandler(request); // URL๋ฅผ ์ด์ฉํด ์ปจํธ๋กค๋ฌ ๊ฐ์ฒด(handler)๋ฅผ ์ฐพ์ ๋ฑ๋กํจ
if (handler == null) {
response.setStatus(HttpServletResponse.SC_NOT_FOUND);
return;
}
MyHandlerAdapter adapter = getHandlerAdapter(handler); // ํด๋น ์ปจํธ๋กค๋ฌ ๊ฐ์ฒด์ ์ด๋ํฐ๋ฅผ ์ฐพ์
// ์ด๋ํฐ๊ฐ request, response ๊ฐ์ฒด๋ฅผ ์ปจํธ๋กค๋ฌ ํ๋ผ๋ฉํ ๋ชจ์์ ๋ง์ถฐ์ ์ ๊ณตํจ
ModelView mv = adapter.handle(request, response, handler);
// ๋ํ ์ด๋ํฐ๊ฐ ์ฌ๋ฌ๊ฐ์ง ํํ์ ๋ฐํ๊ฐ์ ๋์ผํ๊ฒ ์ฒ๋ฆฌํ๋๋ก ๋ง๋ฌ
// [์ปจํธ๋กค๋ฌ๊ฐ ๋ทฐ์ ์ด๋ฆ "name"์ ๋ฐํ], [๋ชจ๋ธ๊ฐ์ฒด(ModelAndView)๋ฅผ ๋ฐํ]
MyView view = viewResolver(mv.getViewName());
view.render(mv.getModel(), request, response);
}
- ํธ๋ค๋ฌ์ ํธ๋ค๋ฌ ์ด๋ํฐ์ ์ฝ๋๋ฅผ ๊ฐ๋จํ๊ฒ ๊ตฌํํ๋ฉด ์๋์ ๊ฐ๋ค. (์ค์ ๋ก๋ ๋ ๋ณต์กํ๋ค.)
โก ํธ๋ค๋ฌ์์ ์ปจํธ๋กค๋ฌ ๊ฐ์ฒด๋ [์คํ๋ง์ HandlerMapping ๊ฐ์ฒด]์ ์ํด ๋งค์นญ๋๋ค.
โก ํธ๋ค๋ฌ ์ด๋ํฐ์์ ํ๋ผ๋ฉํ๋ [์คํ๋ง์ Arugment Resolver ๊ฐ์ฒด]์ ์ํด ๋งค์นญ๋๋ค.
โก ํธ๋ค๋ฌ ์ด๋ํฐ์์ ๋ฐํ๊ฐ์ [์คํ๋ง์ ReturnValue Resolver ๊ฐ์ฒด]์ ์ํด ๋งค์นญ๋๋ค.
โก ์ปจํธ๋กค๋ฌ๊ฐ Model์ ๋ฐํํ๋ฉด [์คํ๋ง์ ViewResolver ๊ฐ์ฒด]๊ฐ ํ์ํ View ๊ฐ์ฒด๋ฅผ ์ฐพ์์ค๋ค.
private Object getHandler(HttpServletRequest request) {
String requestURI = request.getRequestURI();
return handlerMappingMap.get(requestURI); // ํด๋น URL๋ฅผ ์ฒ๋ฆฌํ ์ ์๋ ํธ๋ค๋ฌ(Controller)๋ฅผ ์ฐพ์
}
private MyHandlerAdapter getHandlerAdapter(Object handler) {
// handler(=์ปจํธ๋กค๋ฌ)๊ฐ ์ ํด์ก๋ค๋ฉด ์ปจํธ๋กค๋ฌ๊ฐ ์ฌ์ฉํ๋ [ํ๋ผ๋ฉํ, ๋ฐํ๊ฐ] ํํ๋ฅผ ์ง์ํ๋ ์ด๋ํฐ๋ฅผ ์ฐพ์.
// ์ด๋ํฐ๊ฐ request, response ๋ฑ์ ์ ๋ณด๋ฅผ ์ด์ฉํด์ ํ๋ผ๋ฉํ๋ฅผ ์์ฑํจ.
for (MyHandlerAdapter adapter : handlerAdapters) {
if (adapter.supports(handler)) { // (handler instanceof ์ด๋ํฐ)๊ฐ true์ธ ์ด๋ํฐ๋ฅผ ์ฐพ์;
return adapter;
}
}
@ 2. ์ธํฐ์ ํฐ๋ฅผ ์คํ๋ง ๋น์ผ๋ก ๋ฑ๋ก & ์ค์ ํ๊ธฐ
- ์ธํฐ์
ํฐ๋ ํํฐ์ ๋ง์ฐฌ๊ฐ์ง๋ก ๋ค์ํ ์ค์ ์ ํด์ค ์ ์๋ค. ์ฌ์ฉ๋ฒ๋ ๋น์ทํ ํธ์ด๋ค. (์กฐ๊ธ ๋ค๋ฅด๋ค)
โก @Configuration ๊ฐ์ฒด์์ WebMvcConfigurer ์ธํฐํ์ด์ค๋ฅผ ์ฌ์ฉํ๋ฉด ์ธํฐ์ ํฐ๋ฅผ ์ฝ๊ฒ ๋ฑ๋กํ ์ ์๋ค.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override // WebMvcConfigurer.addInterceptors(...)
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor())
.order(1) // ์ธํฐ์
ํฐ ์์ ์ง์
.addPathPatterns("/**") // ์ธํฐ์
ํฐ๋ฅผ ์ ์ฉํ URL ํจํด
.excludePathPatterns("/css/**", "/*.ico", "/error"); // ์ธํฐ์
ํฐ ์ ์ธ ํจํด
registry.addInterceptor(new LoginCheckInterceptor())
.order(2)
.addPathPatterns("/**")
.excludePathPatterns("/", "/members/add", "/login", "/logout",
"/css/**", "/*.ico", "/error");
}
}
- ์ฐธ๊ณ ๋ก ์คํ๋ง ์ธํฐ์ ํฐ์์๋ ์๋ธ๋ฆฟ ํํฐ์ ๋ค๋ฅธ ๋ฌธ๋ฒ์ผ๋ก ๋งค์ฐ ์์ธํ url pattern ๋งค์นญ์ ์ ๊ณตํด์ค๋ค.
# ๊ฟํ. ์ธํฐ์ ํฐ์ฒ๋ผ ArgumentResolver ํ์ฉํ๊ธฐ
- ์ธํฐ์ ํฐ์์ ์ ์ผํ๊ฒ ์ ๊ทผ, ์กฐ์ํ์ง ๋ชปํ๋ ๊ฒ์ด ์ปจํธ๋กค๋ฌ ๋ฉ์๋์ ์ฃผ์ด์ง๋ ํ๋ผ๋ฉํ์๋ค.
- ์ธํฐ์
ํฐ์ ์ฃผ์ด์ง๋ request, response ์์ฒด๋ฅผ ์กฐ์ํ๋๊ฑด ๋ถ๊ฐ๋ฅํ๊ฒ ๋งํ์๋ค.
๋ฌผ๋ก ํํฐ์์ filter.chain(...)์ ๋๊ธฐ๋ request ์์ฒด๋ฅผ ๋ฐ๊ฟ์น๊ธฐํ๋ ๋ฐฉ๋ฒ์ด ์๊ธดํ๋ฐ...๋ง์ด ๋๋์๋ฆฌ๋ฅผ ํ์
โก ์คํ๋ง์์๋ HandlerMethodArgumentResolver ๋ฅผ ์ด์ฉํด, ArgumentResolver๋ฅผ ์ค๋ฒ๋ผ์ด๋ฉ ํ ์ ์๋ค.
โก ์ด๋ฅผ ์ด์ฉํด์ ์ธํฐ์ ํฐ์์ ํ์ง๋ชปํ ํ๋ผ๋ฉํ ์กฐ์์ ๊ตฌํํ ์ ์๋ค.
๋ฌผ๋ก ๊ฐ๋จํ ์น ์๋น์ค์์ ์ด๋ ๊ฒ๊น์ง ํ ํ์๋ ์์ง๋ง, ์๋น์ค๊ฐ ์ปค์ง๋ค๋ฉด ArugmentResolver๋ฅผ ์ด์ฉํด ์ ์ฉ ์ด๋ ธํ ์ด์ ์ ํ๋ ๋ง๋ค์ด์ ๋งค์ฐ ํธ๋ฆฌํ๊ฒ ์ฌ์ฉ ๊ฐ๋ฅํ๋ค. ์๋ ์์ ๋ฅผ ํตํด ์์๋ณด์.
@1. ๋๋ง์ ์ด๋ ธํ ์ด์ (@Login) ์ ์ํ๊ธฐ
Member ๊ฐ์ฒด์ @Login๋ฅผ ๋ฌ๋ฉด ์๋์ ๊ฐ์ด ์ธ์ ๊ฐ์ ๋ฐ์์ค๋๋ก ArugmentResolver๋ฅผ ๋ง๋ค์ด๋ณด์.
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME) // ๋ฐํ์์ผ๋ก ํด์ค์ผ ๋ฆฌ์กธ๋ฒ๊ฐ ์๋ํ๋ค.
public @interface Login { // ๋ด๊ฐ ์ง์ ๋ง๋ @Login ์ด๋
ธํ
์ด์
}
- HTTP Request์์ ๋ธ๋ผ์ฐ์ ์ ์ ์ก๋ ์ธ์ (HttpSession, ์ฟ ํค)๋ฅผ ๋ฐ์์จ๋ค.
- ํด๋น ์ธ์ ์ loginMember ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด ์ด๋ฅผ ๋ฐํํ๋ค.
- ํด๋น ์ธ์ ์ loginMember ๋ฐ์ดํฐ๊ฐ ์๋ค๋ฉด null์ ๋ฐํํ๋ค.
@GetMapping("/") /* ์คํ๋ง์ @SessionAttribute ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ */
public String homeLoginSpring(
@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember,
Model model) {
//์ธ์
์ ํ์ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด home
if (loginMember == null) { return "home";}
//์ธ์
์ด ์ ์ง๋๋ฉด ๋ก๊ทธ์ธ์ผ๋ก ์ด๋
model.addAttribute("member", loginMember);
return "loginHome";
}
@GetMapping("/") /* ๋ด๊ฐ ๋ง๋ ArugmentResolver๋ฅผ ์ด์ฉํด @Login ํ๊ทธ๋ฅผ ๋ง๋ค์ด ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ */
public String homeLoginArgumentResolver(@Login Member loginMember, Model model) {
//์ธ์
์ ํ์ ๋ฐ์ดํฐ๊ฐ ์์ผ๋ฉด home
if (loginMember == null) {
return "home";
}
//์ธ์
์ด ์ ์ง๋๋ฉด ๋ก๊ทธ์ธ์ผ๋ก ์ด๋
model.addAttribute("member", loginMember);
return "loginHome";
}
@ 2. ํด๋น ์ด๋ ธํ ์ด์ ์ ์ฒ๋ฆฌํ๋ ArugmentResolver ๊ตฌํํ๊ธฐ
- HandlerMethodArgumentResolver ์ธํฐํ์ด์ค๋ฅผ ์ด์ฉํ๋ฉด ์์ฝ๊ฒ ๊ตฌํํ ์ ์๋ค.
โก supportsParameter(...)๋ฅผ ์ด์ฉํด์ ํด๋น ๋ฆฌ์กธ๋ฒ๋ฅผ ์ ์ฉํ ํ๋ผ๋ฉํ๋ฅผ ์ ์ํ๋ค. (๋ฐํ๊ฐ์ด true์ธ ๊ฒฝ์ฐ์๋ง ์ ์ฉ)
โก resolverArgument(...) ๋ฅผ ์ด์ฉํด์ ํด๋น ํ๋ผ๋ฉํ์ ์ด๋ ํ ๊ฐ์ ๋ฃ์ด์ค๊ฑด์ง ์ ์ํ๋ค.
@Slf4j
public class LoginMemberArgumentResolver implements HandlerMethodArgumentResolver {
@Override
public boolean supportsParameter(MethodParameter parameter) {
// ํ๋ผ๋ฉํ์ @Login ์ด๋
ธํ
์ด์
์ด ๋ฌ๋ ธ๋์ง ์ฌ๋ถ
boolean hasLoginAnnotation = parameter.hasParameterAnnotation(Login.class);
// ํ๋ผ๋ฉํ์ ํ์
์ด Member๋ก ๋ฐ์ธ๋ฉ ๊ฐ๋ฅํ์ง ์ฌ๋ถ (isAssignableFrom)
boolean hasMemberType = Member.class.isAssignableFrom(parameter.getParameterType());
return hasLoginAnnotation && hasMemberType; // true์ธ ๊ฒฝ์ฐ์๋ง resolveArgument() ์คํ
}
@Override
public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
// Resolver์์ requset ๊ฐ์ฒด๋ฅผ ๋ฐ์์ค๋ ๋ฐฉ๋ฒ
HttpServletRequest request = (HttpServletRequest) webRequest.getNativeRequest();
// HttpSession ๊ฐ์ฒด๋ฅผ ๋ฐ์์์ ํด๋น ๋ฉค๋ฒ์ ์ธ์
ID๋ฅผ ์กฐํํ๋ค.
HttpSession session = request.getSession(false);
// ์ธ์
์ด ์๋ค๋ฉด null, ์๋ค๋ฉด ํ์ฌ Login_member ์ธ์
๊ฐ ์ ์ฒด๋ฅผ ๋ฐํํ๋ค.
if (session == null) {
return null;
}
return session.getAttribute(SessionConst.LOGIN_MEMBER);
}
}
// ์ฐธ๊ณ ๋ก SessionConst๋ ์ฐ๋ฆฌ๊ฐ ์์ ์์ ์ง์ ๋ง๋ ์์์ฉ ๊ฐ์ฒด์ด๋ค. ์คํ๋ง ๊ฐ์ฒด๊ฐ ์๋๋ค
public class SessionConst {
public static final String LOGIN_MEMBER = "loginMember";
}
- ์ด๋ ๊ฒ ๋ง๋ ArugmentResolver๋ ์๋์ ๊ฐ์ด ์ถ๊ฐํ ์ ์๋ค.
โก @Configuration ๊ฐ์ฒด์ WebMvcConfigurer๋ฅผ ์์๋ฐ์ ์ถ๊ฐํ๋ค. ์ธํฐ์ ํฐ ์ถ๊ฐ์ ๋น์ทํ๋ค.
@Configuration
public class WebConfig implements WebMvcConfigurer {
@Override // ๋ด๊ฐ ๋ง๋ @Login ๊ณผ ArgumentResolver ๋ฑ๋ก
public void addArgumentResolvers(List<HandlerMethodArgumentResolver> resolvers) {
resolvers.add(new LoginMemberArgumentResolver());
}
@Override // ์ธํฐ์
ํฐ ๋ฑ๋ก
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LogInterceptor())
.order(1)
.addPathPatterns("/**")
.excludePathPatterns("/css/**", "/*.ico", "/error");
registry.addInterceptor(new LoginCheckInterceptor())
.order(2)
.addPathPatterns("/**")
.excludePathPatterns("/", "/members/add", "/login", "/logout",
"/css/**", "/*.ico", "/error");
}
}
'๐ฑ Spring Framework > Spring MVC' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Spring ์์ธ์ฒ๋ฆฌ - API, @ExceptionHandler (0) | 2021.08.30 |
---|---|
Spring ์์ธ์ฒ๋ฆฌ - ์ค๋ฅํ์ด์ง(404,500) (0) | 2021.08.30 |
Spring Login#1 ์ฟ ํค์ ์ธ์ (0) | 2021.08.29 |
Spring Bean Validation#2 ์คํ๋ง ๋น ๊ฒ์ฆ (0) | 2021.08.29 |
Spring Vaildation#1 ๊ฒ์ฆ (0) | 2021.08.29 |
๋ธ๋ก๊ทธ์ ์ ๋ณด
JiwonDev
JiwonDev