1. interceptor ( 인터셉터 ) 란 ?
클라이언트의 요청과 응답을 가로채고 처리하는 미들웨어 역할을 한다.
interceptor는 특정 URL 패턴에 대해 요청 전처리 , 후처리 , 응답 전처리 , 응답 후처리 등의 작업을 수행할 수 있다.
Interceptor를 구현하기 위해서는 HandlerInterceptor 인터페이스를 구현하고 해당 인터페이스의 메소드를 오버라이딩하여 원하는 작업을 구현하면 된다.
Spring이 제공하는 기술로 , 디스패처 서블릿( Dispatcher Servlet ) 이 컨트롤러를 호출하기 전과 후에 요청과 응답을 참조하거나 가공할 수 있는 기능을 제공한다.
즉 , 웹 컨테이너 ( 서블릿 컨테이너 ) 에서 동작하는 필터와 달리 인터셉터는 스프링 컨텍스트에서 동작하는 것이다.
예를 들어 로그인이 되어있지 않을 때 로그인후 사용자가 요청했던 주소로 갈수 있도록 할 수 있다.
package com.icia.board.config;
import org.springframework.web.servlet.HandlerInterceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
public class LoginCheckInterceptor implements HandlerInterceptor {
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws IOException {
// 사용자가 요청한 주소 확인
String requestURI = request.getRequestURI();
System.out.println("requestURI = " + requestURI);
// 세션객체 생성
HttpSession session = request.getSession();
// 세션에 저장된 로그인 정보 확인
if(session.getAttribute("loginEmail") == null) {
// 로그인 하지 않았다면 로그인페이지로 보내면서 요청한 주소값도 같이 보낸다.
response.sendRedirect("/member/login?redirectURI="+requestURI);
return false;
}else {
// 로그인 상태라면 요청한 페이지로 보냄(거르지 않는다)
return true;
}
}
}
- HandlerInterceptor 인터페이스를 구현하고 preHandle 메소드를 오버라이딩해서 요청 전처리 작업을 구현한다.
- preHandle 메소드의 매개변수로 HttpServletRequest와 HttpServletResponse, Object handler를 받는다.
- HttpServletRequest 객체를 통해 클라이언트의 요청 정보를 확인한다.
- HttpServletResponse 객체를 통해 클라이언트로의 응답을 처리한다.
- HttpSession 객체를 생성하여 세션에 저장된 로그인 정보를 확인한다.
- getSession 메소드를 호출할때 파라미터로 true를 전달하여 세션이 없을 경우 새로 생성한다.
- 세션에 "loginEmail"에 값이 없다면 로그인하지 않는 걸로 간주하여 로그인페이지로 리다이렉트하고 요청한 주소값을 함께 전달한다.
- 로그인 상태라면 요청한 페이지로 진행하도록 true를 반환한다.
즉 , 이 LoginCheckInterceptor는 세션에 "loginEmail" 값이 없을 경우 로그인 여부를 체크하고 로그인하지 않은 상태라면 로그인페이지로 리다이렉트하는 역할이다.
package com.icia.member.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
@Configuration // 해당 클래스에 정의한 설정정보를 스프링 컨테이너에 등록
public class WebConfig implements WebMvcConfigurer {
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new LoginCheckInterceptor()) // 인터셉터로 등록한 클래스
.order(1) // 해당 인터셉터의 우선 순위
.addPathPatterns("/**") // 인터셉터로 체크할 주소(모든 주소)
.excludePathPatterns("/","/member/save","/member/login","/member/login/axios","/js/**","/css/**","/image/**","/*.ico","/favicon/**")
// 인터셉터 검증을 하지 않을 주소
}
}
- @Configuration 어노테이션은 해당 클래스가 스프링의 설정 정보를 담고 있는 클래스임을 나타낸다.
- addInterceptors 메소드를 오버라이딩하여 인터셉터를 등록하는 작업을 수행한다.
- InterceptorRegistry 객체를 사용해 인터셉터를 등록한다.
- addInterceptor 메소드를 호출하여 LoginCheckInterceptor 인스턴스를 등록한다.
이 인터셉터는 로그인 체크를 수행한다. - order 메소드를 사용하여 등록한 인터셉터의 우선 순위를 설정한다. 낮은 숫자일 수록 우선순위가 높다.
- addPathPatterns 메소드를 사용하여 인터셉터가 적용되지 않을 주소 패턴을 저장한다.
여기서는 "/**" 패턴을 사용하여 모든 주소에 대해 인터셉터를 적용했다. - excludePathPatterns 메소드를 사용하여 인터셉터가 적용되지 않을 주소 패턴을 지정한다.
여기서는 로그인 , 회원가입 , 정적 리소스에 대한 주소등을 제외하고 인터셉터를 적용하도록 했다.
Controller
@PostMapping("/login")
public String memberLogin(@ModelAttribute MemberDTO memberDTO, HttpSession session,
@RequestParam("redirectURI") String redirectURI) {
boolean loginResult = memberService.login(memberDTO);
if ( loginResult ) {
session.setAttribute("loginEmail", memberDTO.getMemberEmail());
return "redirect:"+redirectURI;
}else {
return "memberPages/memberLogin";
}
}
}
Post 방식으로 "/login"주소에 매핑되어 있고 회원 로그인을 처리하고 세션에 로그인 정보를 저장한다.
로그인 성공시 이전 페이지로 리다이렉트하고 실패시 로그인 페이지를 다시 표시한다.
memberSave.html
<div id="section">
<form action="/member/login" method="post">
<input type="hidden" name="redirectURI" th:value="${redirectURI}">
<input type="text" name="memberEmail" placeholder="이메일"><br>
<input type="text" name="memberPassword" placeholder="비밀번호"><br>
<p id="login-result" style="color: red; display: none">이메일 또는 비밀번호가 틀립니다!</p><br>
<input type="button" value="로그인" onclick="login()">
</form>
</div>
input 타입에 redirectURI을 추가한다.
<script>
const login = () => {
const email = document.querySelector('input[name="memberEmail"]').value;
const password = document.querySelector('input[name="memberPassword"]').value;
const redirectURI = document.querySelector('input[name="redirectURI"]').value;
axios({
method: "post",
url: "/member/login/axios",
data: {
memberEmail: email,
memberPassword: password
}
}).then(res => {
location.href= redirectURI;
}).catch(err => {
document.getElementById("login-result").style.display="block";
})
}
</script>
axios로 로그인을 처리한다.
'Spring > Spring boot icia 73일차' 카테고리의 다른 글
Spring boot Pk,FK 참조관계 맺기 (0) | 2023.06.07 |
---|---|
Spring boot 날짜 , builder , Modifying (0) | 2023.06.07 |
Spring boot 게시판 단일파일 , 다중파일 처리 (0) | 2023.06.07 |
Spring boot 게시판 수정 , 삭제 (0) | 2023.06.07 |