์ด๋ฒ ๊ธ์์๋ ์๋ธ๋ฆฟ ํํฐ(Servlet Filter)์ ๊ฐ๋ ์ ๋ํด์ ์์๋ณด๊ณ , '์์ฒญ ๋ก๊ทธ ์์ '์ '์ธ์ฆ ์ฒดํฌ ์์ '๋ฅผ ํตํด์ ์ด๋ป๊ฒ ํํฐ๋ฅผ ์ฌ์ฉํ๋์ง ์์๋ณด๊ณ ์ ํ๋ค.
1. ๊ฐ๋ ๐
๐ 1. ํํฐ ํ๋ฆ
ํํฐ๋ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ค์๊ณผ ๊ฐ์ ํ๋ฆ์ ๊ฐ์ง๋ค.
HTTP ์์ฒญ → WAS → ํํฐ → ์๋ธ๋ฆฟ(Dispatcher Servlet) → ์ปจํธ๋กค๋ฌ
ํํฐ๋ฅผ ์ ์ฉํ๋ฉด ํํฐ๊ฐ ํธ์ถ๋๊ณ ๊ทธ๋ฆฌ๊ณ ์๋ธ๋ฆฟ์ด ํธ์ถ๋๋ค. ์ฆ, ์๋ธ๋ฆฟ์ด ํธ์ถ๋๊ธฐ ์ ์ ํํฐ๊ฐ ํธ์ถ๋๋ ๊ฒ์ด๋ค. ๊ทธ๋ ๊ฒ ๋๋ฌธ์ ๋ชจ๋ ๊ณ ๊ฐ์ ์์ฒญ ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๊ฑฐ๋ ์ธ์ฆ ์ฒดํฌ(๋ก๊ทธ์ธ ์ฌ๋ถ ๋ฑ)๋ฑ์ ํ์๋ฅผ ํํฐ๋ฅผ ์ด์ฉํด์ ํ ์ ์๋ค.
๐ 2. ํํฐ ์ ํ
ํํฐ์์๋ ๋ก๊ทธ์ธํ์ง ์์ ์ฌ์ฉ์์ ์ ๊ทผ๊ณผ ๊ฐ์ด ์ ์ ํ์ง ์์ ์์ฒญ์ ๋ํ์ฌ ํ๋จํ๊ณ ๊ฑฐ๊ธฐ์์ ๋์ ๋ผ ์ ์๋ค.
(1) ๋ก๊ทธ์ธํ ์ฌ์ฉ์์ธ ๊ฒฝ์ฐ
HTTP ์์ฒญ → WAS → ํํฐ(๋ก๊ทธ์ธ O) → ์๋ธ๋ฆฟ → ์ปจํธ๋กค๋ฌ
(2) ๋ก๊ทธ์ธํ์ง ์์ ์ฌ์ฉ์์ธ ๊ฒฝ์ฐ
HTTP ์์ฒญ → WAS → ํํฐ(๋ก๊ทธ์ธ X)
๐ 3. ํํฐ ์ฒด์ธ
ํํฐ๋ ์ฒด์ธ์ผ๋ก ๊ตฌ์ฑ๋๋ค.
HTTP ์์ฒญ → WAS → ํํฐ1 → ํํฐ2 → ํํฐ3 → ์๋ธ๋ฆฟ → ์ปจํธ๋กค๋ฌ
๊ทธ๋์ ์ฌ๋ฌ ํํฐ๋ฅผ ์ ์ฉํ ์ ์๋ค. ์๋ฅผ ๋ค์ด ๋ก๊ทธ๋ฅผ ๋จ๊ธฐ๋ ํํฐ๋ฅผ ๋จผ์ ์ ์ฉํ๊ณ ๊ทธ๋ฆฌ๊ณ ๋ก๊ทธ์ธ ์ฌ๋ถ๋ฅผ ์ฒดํฌํ๋ ํํฐ๋ฅผ ์ ์ฉํ ์ ์๋ค.
๐ 4. ํํฐ ์ธํฐํ์ด์ค
public interface Filter {
default void init(FilterConfig filterConfig) throws ServletException {}
void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException;
default void destroy() {}
}
ํํฐ๋ฅผ ์ฌ์ฉํ๊ธฐ ์ํด์๋ ํํฐ ์ธํฐํ์ด์ค๋ฅผ ๊ตฌํํ๊ณ ๋ฑ๋กํ๋ฉด ๋๋ค. ๊ทธ๋ฌ๋ฉด ์๋ธ๋ฆฟ ์ปจํ ์ด๋๊ฐ ํํฐ๋ฅผ ์ฑ๊ธํค ๊ฐ์ฒด๋ก ์์ฑํ๊ณ ๊ด๋ฆฌํ๋ค. ๊ฐ๊ฐ์ ๋ฉ์๋๋ ๋ค์๊ณผ ๊ฐ์ ์ญํ ์ ํ๋ค.
- init()
ํํฐ ์ด๊ธฐํ ๋ฉ์๋
์๋ธ๋ฆฟ ์ปจํ ์ด๋๊ฐ ์์ฑ๋ ๋ ํธ์ถ๋๋ค. - doFilter()
๊ณ ๊ฐ์ ์์ฒญ์ด ์ฌ ๋๋ง๋ค ํด๋น ๋ฉ์๋๊ฐ ํธ์ถ๋๋ค.
ํํฐ ๋ก์ง์ ๊ตฌํํ๋ฉด ๋๋ค. - destroy()
ํํฐ ์ข ๋ฃ ๋ฉ์๋
์๋ธ๋ฆฟ ์ปจํ ์ด๋๊ฐ ์ข ๋ฃ๋ ๋ ํธ์ถ๋๋ค.
init()๊ณผ destroy()๋ default ๋ฉ์๋์ด๋ฏ๋ก ์ค๋ฒ๋ผ์ด๋ฉ์ ๊ผญ ํด์ผ๋ง ํ๋ ๊ฒ์ ์๋๋ค.
2. ์์ฒญ ๋ก๊ทธ ์์ ๐ช
@Slf4j
public class LogFilter implements Filter {
@Override
public void init(FilterConfig filterConfig) throws ServletException {
log.info("log filter init");
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest httpRequest = (HttpServletRequest) request;
String requestURI = httpRequest.getRequestURI();
String uuid = UUID.randomUUID().toString(); // HTTP ์์ฒญ์ ๊ตฌ๋ถํ๊ธฐ ์ํ ๊ฒ
try{
log.info("REQUEST [{}][{}]", uuid, requestURI);
chain.doFilter(request, response);
} catch (Exception e) {
throw e;
} finally {
log.info("RESPONSE [{}][{}]", uuid, requestURI);
}
}
@Override
public void destroy() {
log.info("log filter destroy");
}
}
ํ๋ผ๋ฏธํฐ ํ์ ์ด HttpServletRequest๊ฐ ์๋ ServletRequest์ธ ์ด์ ๋ ํํฐ ์ธํฐํ์ด์ค๋ HTTP ์์ฒญ์ด ์๋ ๊ฒฝ์ฐ๊น์ง ๊ณ ๋ คํด์ ๋ง๋ค์๊ธฐ ๋๋ฌธ์ด๋ค. ๊ทธ๋์ request๋ฅผ HttpServletRequest๋ผ๊ณ ๋ค์ด์บ์คํ ํด์ฃผ์๋ค.
chain.doFilter(request, response)๋ฅผ ์ด์ฉํ์ฌ ๋ค์ ํํฐ๊ฐ ์์ผ๋ฉด ๋ค์ ํํฐ๋ฅผ ํธ์ถํ๊ณ , ์์ผ๋ฉด ์๋ธ๋ฆฟ์ ํธ์ถํ๋ค. ์ด๊ฑธ ์๋ตํ๋ฉด ๋ค์ ๋จ๊ณ๋ก ์งํ์ด ๋์ง ์๋๋ค.
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean logFilger() {
FilterRegistrationBean<Filter> filterRegistrationBean
= new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LogFilter()); // ๋ฑ๋กํ ํํฐ ์ง์
filterRegistrationBean.setOrder(1); // ์ฒด์ธ ์์ ์ง์
filterRegistrationBean.addUrlPatterns("/*"); // ํํฐ๋ฅผ ์ ์ฉํ URL ํจํด ์ง์
return filterRegistrationBean;
}
}
FilterRegistrationBean์ ์ด์ฉํด์ ๋ฑ๋กํด ์ฃผ๋ฉด ๋๋ค.
setFilter()๋ฅผ ์ด์ฉํด์ ์ฌ์ฉํ ํํฐ๋ฅผ ๋ฑ๋กํ๊ณ , setOrder()๋ฅผ ์ด์ฉํด์ ์ฒด์ธ ์์๋ฅผ ์ ํ๊ณ , addUrlPatterns()๋ฅผ ์ด์ฉํด์ ํํฐ๋ฅผ ์ ์ฉํ URL์ ์ง์ ํ๋ฉด ๋๋ค.
์คํ์์ผ ๋ณด๋ฉด ๋ก๊ทธ๋ ์๋์ ๊ฐ์ด ๋์ค๊ฒ ๋๋ค.
2023-04-29T21:58:44.599+09:00 INFO 16520 --- [ main] com.filter.LogFilter : log filter init
2023-04-29T21:58:47.135+09:00 INFO 16520 --- [nio-8080-exec-1] com.filter.LogFilter : REQUEST [14e2840a-84d3-43a3-9275-f03fab226e31][/]
2023-04-29T21:58:47.661+09:00 INFO 16520 --- [nio-8080-exec-1] com.filter.LogFilter : RESPONSE [14e2840a-84d3-43a3-9275-f03fab226e31][/]
2023-04-29T21:59:05.150+09:00 INFO 16520 --- [ionShutdownHook] com.filter.LogFilter : log filter destroy
3. ์ธ์ฆ ์ฒดํฌ ์์ ๐
@Slf4j
public class LoginCheckFilter implements Filter {
// ์ธ์ฆ ์ฒดํฌ๋ฅผ ํ์ง ์์ ๊ฒ๋ค
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 (isLoginCheckPath(requestURI)) {
log.info("์ธ์ฆ ์ฒดํฌ ๋ก์ง ์คํ {}", requestURI);
HttpSession session = httpRequest.getSession(false);
// ์ธ์ฆ์ด ๋์ง ์์ ์ฌ์ฉ์์ธ ๊ฒฝ์ฐ
if (...) {
log.info("๋ฏธ์ธ์ฆ ์ฌ์ฉ์ ์์ฒญ {}", requestURI);
//๋ก๊ทธ์ธ์ผ๋ก redirect
httpResponse.sendRedirect("/login?redirectURL=" + requestURI);
// ๋ฏธ์ธ์ฆ ์ฌ์ฉ์๋ ๋ ์ด์ ์งํํ์ง ์๊ธฐ
return;
}
}
// ๋ก๊ทธ์ธ ์ฌ๋ถ๋ฅผ ํ์ธํ์ง ์์๋ ๋๋ ๊ฒฝ๋ก์ด๊ฑฐ๋
// ์ธ์ฆ๋ ์ฌ์ฉ์์ธ ๊ฒฝ์ฐ
// ๊ณ์ ์งํ
chain.doFilter(request, response);
} catch (Exception e) {
throw e;
} finally {
log.info("์ธ์ฆ ์ฒดํฌ ํํฐ ์ข
๋ฃ {}", requestURI);
}
}
private boolean isLoginCheckPath(String requestURI) {
return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
}
}
@Configuration
public class WebConfig {
@Bean
public FilterRegistrationBean loginCheckFilger() {
FilterRegistrationBean<Filter> filterRegistrationBean
= new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LoginCheckFilter()); // ๋ฑ๋กํ ํํฐ ์ง์
filterRegistrationBean.setOrder(2); // ์ฒด์ธ ์์ ์ง์
filterRegistrationBean.addUrlPatterns("/*"); // ํํฐ๋ฅผ ์ ์ฉํ URL ํจํด ์ง์
return filterRegistrationBean;
}
}
'ํ, ํ์๊ฐ์ , ๋ก๊ทธ์ธ, css'์ ๊ฐ์ ๊ณณ์๋ ์ธ์ฆ๊ณผ ๋ฌด๊ดํ๊ฒ ํญ์ ์ ๊ทผํ ์ ์์ด์ผ ํ๋ค. ๊ทธ๋์ whitelist๋ผ๋ ๊ฒ์ ๋ง๋ค์ด์ ์ธ์ฆ ์ฒดํฌ ๋ก์ง์์ ๋ฐฐ์ ํด ์ฃผ์๋ค.
์ธ์ฆ์ด ํ์ฉ๋์ง ์์ผ๋ฉด login ํ๋ฉด์ผ๋ก ์ด๋ํ๊ฒ ํ์๋๋ฐ, ๋ค์ redirectURL์ ํ๋ผ๋ฏธํฐ๋ก ๋ถ์ฌ์ฃผ์๋ค. ๊ทธ ์ด์ ๋ ๋ก๊ทธ์ธ์ ํ ์ดํ ๋ค์ ์๋ ํ์ด์ง๋ก ๋์์ค๊ฒ ํ๊ธฐ ์ํด์๋ค.
์ถ๊ฐ์ ์ผ๋ก ์ธํฐ์ ํฐ(Interceptor)์ ๋ฌ๋ฆฌ ํํฐ๋ doFilter(request, response)๋ฅผ ํธ์ถํ ๋ request์ response๋ฅผ ๋ค๋ฅธ ๊ฐ์ฒด๋ก ๋ฐ๊ฟ ์ ์๋ค๋ ๊ฒ์ ์ฐธ๊ณ ์ฌํญ์ผ๋ก ์์๋์.
ํด๋น ๊ธ์ ๊น์ํ ๋์ '์คํ๋ง MVC 2ํธ - ๋ฐฑ์๋ ์น ๊ฐ๋ฐ ํ์ฉ ๊ธฐ์ '์ ์ฐธ๊ณ ํ์์ต๋๋ค.
'๐ ์คํ๋ง > ๊ธฐ๋ณธ ๊ฐ๋ ' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring] ๊ฒ์ฆ(Validation) - BindingResult, FieldError, ObjectError (0) | 2023.05.01 |
---|---|
์คํ๋ง ์ธํฐ์ ํฐ(Spring Interceptor) (0) | 2023.04.30 |
๋ฉ์์ง & ๊ตญ์ ํ (Message & Internationalization) (0) | 2023.04.25 |
HTTP ์๋ต(์ ์ ๋ฆฌ์์ค, ๋ทฐ ํ ํ๋ฆฟ, HTTP ๋ฉ์์ง) ์ฒ๋ฆฌ (0) | 2023.04.21 |
HTTP ์์ฒญ(ํค๋, ํ๋ผ๋ฏธํฐ, ๋ฉ์์ง) ์ฒ๋ฆฌ (0) | 2023.04.20 |