스프링 MVC 2편 - 백엔드 웹 개발 활용 기술 - (39) 로그인 처리 - 서블릿 필터 - 인증 체크
인프런 스프링 MVC 2편 - 백엔드 웹 개발 활용 기술편을 학습하고 정리한 내용 입니다.
서블릿 필터 - 인증 체크
로그인 되지 않은 사용자는 상품 관리 뿐만이 아니라 미래에 개발될 페이지에도 접근하지 못하도록 하자.
인증 체크 필터 구현
hello.login.web.filter.LoginCheckFilter
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@Slf4j
public class LoginCheckFilter implements Filter {
private static final String[] whitelist = {"/", "/members/add", "/login", "/logout", "/css/*"};
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) servletRequest;
String requestURI = request.getRequestURI();
HttpServletResponse response = (HttpServletResponse) servletResponse;
try {
log.info("인증 체크 필터 시작 {}", requestURI);
if (isLoginCheckPath(requestURI)) {
log.info("인증 체크 로직 실행 {}", requestURI);
HttpSession session = request.getSession();
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
log.info("미인증 사용자 요청 {}", requestURI);
// 로그인페이지로 redirect
response.sendRedirect("/login?redirectURL="+requestURI);
return;
}
}
filterChain.doFilter(servletRequest, servletResponse);
} catch (Exception e) {
throw e;
} finally {
log.info("인증 체크 로직 종료 {}", requestURI);
}
}
/**
* 화이트리스트인 경우 인증 체크 X
* */
private boolean isLoginCheckPath(String requestURI) {
return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
}
}
먼저 필터를 만들어 줬다. 여기서 또 처음 알았던 점이 implements 하면서 default 메서드는 구현 하지 않아도 된다는 점이다.
그래서 이번엔 doFilter()만 구현했다.
1
private static final String[] whitelist = {"/", "/members/add", "/login", "/logout", "/css/*"};
필터를 적용해도 홈, 회원 가입, 로그인 화면, css 같은 리소스에는 접근 가능해야 한다.
그래서 이 url 접근이 오면 인증을 생략하게 하는 로직을 넣어야 한다.
1
2
3
private boolean isLoginCheckPath(String requestURI) {
return !PatternMatchUtils.simpleMatch(whitelist, requestURI);
}
스프링이 제공하는 유틸성 클래스 PatternMatchUtils를 이용해 화이트 리스트에 있는 문자열과, 사용자가 접근하는 url에
겹치는 부분이 있으면 false, 겹치는 부분이 없으면 true를 반환하도록 설계
simpleMatch(): 어떤 문자열이 특정 패턴에 매칭 되는지를 검사함.
1
2
3
4
5
6
7
8
9
10
if (isLoginCheckPath(requestURI)) {
log.info("인증 체크 로직 실행 {}", requestURI);
HttpSession session = request.getSession();
if (session == null || session.getAttribute(SessionConst.LOGIN_MEMBER) == null) {
log.info("미인증 사용자 요청 {}", requestURI);
// 로그인페이지로 redirect
response.sendRedirect("/login?redirectURL="+requestURI);
return;
}
}
이제 isLoginCheckPath()로 화이트 리스트를 체크하고
세션을 확인하고, 세션이 있는데 로그인 관련된 세션이 있는지 확인하고
없으면
1
response.sendRedirect("/login?redirectURL="+requestURI);
로그인 페이지로 리다이렉트 시키는 로직이다.
그런데 여기서 ?redirectURL="+requestURI 가 있는데
이는 로그인 후에 사용자가 원래 접근 하려던 페이지로 다시 보내주기 위함이다.
1
filterChain.doFilter(servletRequest, servletResponse);
로그인 필터에 안 걸렸다면 이제 다음 필터로 넘어가도록 선언해 주면 끝난다.
인증 체크 필터 등록
hello.login.WebConfig
1
2
3
4
5
6
7
8
@Bean
public FilterRegistrationBean loginCheckFilter() {
FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
filterRegistrationBean.setFilter(new LoginCheckFilter());
filterRegistrationBean.setOrder(2); // 필터 순서
filterRegistrationBean.addUrlPatterns("/*"); // 모든 URL
return filterRegistrationBean;
}
저번에 로그 필터를 등록 한 것처럼 FilterRegistrationBean을 사용해 등록했다.
필터 순서를 로그 필터 이후로 등록하기 위해 2로 등록했다.
로그인 컨트롤러 리다이렉트 처리
마지막으로 ?redirectURL="+requestURI 이 요청을 처리하기 위해
로그인 컨트롤러를 약간 수정하자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
@PostMapping("/login")
public String loginV4(@Validated @ModelAttribute("loginForm") LoginForm form, BindingResult result,
@RequestParam(defaultValue = "/") String redirectURL,
HttpServletRequest request) {
if (result.hasErrors()) {
return "login/loginForm";
}
Member loginMember = loginService.login(form.getLoginId(), form.getPassword());
if (loginMember == null) {
result.reject("loginFail", "아이디 또는 비밀번호가 맞지 않습니다.");
return "login/loginForm";
}
// 로그인 성공 처리
// 세션이 있으면 있는 세션 반환, 없으면 신규 세션을 생성
HttpSession session = request.getSession();
// 세션에 로그인 회원 정보를 보관
session.setAttribute(SessionConst.LOGIN_MEMBER, loginMember);
return "redirect:" + redirectURL;
}
먼저 파라미터에
1
@RequestParam(defaultValue = "/") String redirectURL
다음과 같이 ?redirectURL="+requestURI를 받아주기 위해 @RequestParam을 사용했고,
그냥 로그인 페이지에서 로그인 한 것 일수도 있기 때문에 defaultValue = "/"을 넣어줬다.
그다음엔
1
return "redirect:" + redirectURL;
이렇게 리다이렉트 시키면 끝이다.
이제 결과를 보자.

메인 페이지에서 /items로 직접 접근했을 때 로그인 페이지로 가버리고 ?redirectURL=/items가 생겼다.

로그를 보면
로그 필터 -> 인증 체크 필터 -> 인증 체크 파이널 -> 로그 파이널 이 순서로 실행 된 걸 볼 수 있다.

로그인 해주면 바로 items로 이동하게 됐다.
공통 관심사를 서블릿 필터를 사용해서 해결한 덕분에 향후 로그인 관련 정책이 변경되어도 이 부분만 변경하면 된다.
댓글남기기