본문 바로가기
Spring

[인터셉터]

by moca7 2024. 11. 5.

 

 

 

ㅁ 브라우저 주소창에 url을 직접 써서 요청해보기

 

 

 

 

- 로그인 후 이용가능한 페이지들의 url을 기억했다가 직접 주소창에 써서 요청하면 보여진다. 

 

- 절대 그렇게 포워딩 되어서는 안된다. alert 띄우면서 메인페이지로 보내야 한다. 

 

 

 

 

 

 

 

- 컨트롤러에서 url 요청이 오면 별도의 조건처리 없이 무조건 이동되게 하고 있다.

이 페이지에 진입할 권한이 있는지를 체크해야 한다.

- 세션으로부터 로그인한 회원정보가 없다면 컨트롤러의 이동시키는 메소드에서 이동이 불가능하게끔 막아두면 된다.

 

 

- 근데 로그인 후에 이용할 수 있는 페이지들이 더 있을건데 매번 그 메소드들마다 일일이 작성하기에는 번거롭다.

- 인터셉터 기술을 사용한다. 필터로도 가능한데 필터와 인터셉터간에 시기가 다르고 컨테이너 차이도 있다.

 

 

 

 

ㅁ 인터셉터와 필터

- 인터셉터는 스프링에서 제공하는 기술이다. 스프링이기 때문에 가능하다.

 

- Dispatcher Servlet에서 해당 Controller가 실행되기 이전,

Controller에서 Dispatcher Servlet으로 반환하는 시점에서 낚아채서 무언갈 할 수 있다.

(컨트롤러가 실행되기 전, 실행된 후)

 

- 로그인되어있는지 여부, 이 페이지에 진입할 권한이 있는지를 체크함.

- 권한체크에 어떤 기술? 스프링의 인터셉터 기술.

 

 

 

- 비슷한게 필터다.

필터도 비슷한 개념이다.

그런데 필터는 실행되는 시점이 다르고 필터를 구동시켜주는 컨테이너가 다르다.

- 필터도 똑같이 본격적으로 요청처리가 실행되기 전, 후에 낚아채서 무언갈 할수 있는데

필터는 파란색박스다.

url 요청이 들어왔을 때 Dispatcher Servlet이 구동되기 전, 구동된 후에 실행되는 것이 필터다.

- 필터는 스프링에서만 쓰는게 아니다. 

필터는 스프링의 기술이 아니다. 서블릿과 관련된 기술이다. 서블릿이 본격적으로 구동되기 전, 후에 낚아채서 전처리 후처리한다.

 

- ~면 필터이용. ~면 인터셉터 이용.

- 제공되는 기술이 다르다. 필터는 서블릿관련기술이고 인터셉터는 스프링 관련 기술이다.

필터는 ~

 

 

- 인터셉터도 특정 url에만 작동하게 매핑한다.

필터는 스프링을 쓰지 않아도 쓸 수 있다. 인터셉터는 스프링을 이용해야만 가능하다.

 

 

- 수업은 로그인.

- 프로젝트는 권한체크용 인터셉터로 이용해보세요. 직급, 직책별로 이용할 수 있게끔.

 

 

 

 

 

 

※ Interceptor (정확히는 HandlerInterceptor)

- servlet에서 특정 controller가 실행되기 전, 실행된 후에 낚아채서 실행할 내용을 정의할 수 있다.

- 특정 요청을 할 수 있는 회원이 맞는지(로그인 여부 판단),

특정 요청을 할 수 있는 권한이 맞는지(회원의 권한 체크)

 

- preHandle(전처리 담당 메소드) : DispatcherServlet이 특정 Controller를 호출하기 전에 낚아채는 영역

- postHandle(후처리 담당 메소드) : Controller에서 요청 처리 후 DispatcherServlet으로 뷰 정보가 돌아가는 순간 낚아채는 영역

- 우린 전처리만 지금 진행한다.

 

 

 

 

 

 

ㅁ com.br.spring.interceptor 패키지 생성

 

ㅁ com.br.spring.interceptor에 LoginCheckInterceptor (일반) 클래스 생성

 

 
package com.br.spring.interceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.web.servlet.FlashMap;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.support.RequestContextUtils;

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; // 컨트롤러 실행되지 않도록
     
    }
   
  }
 
 
}
 

 

 

- 단순한 일반 클래스가 아니라 인터셉터 역할을 수행할 수 있는 클래스 형태로 만들어야 한다.

 

- HandlerInterceptor를 implements한다.

 

- ctrl을 누르고 클릭해서 HandlerInterceptor를 가본다. 

가서 메소드 preHandle을 가져온다. 오버라이딩이기 때문에 매개변수의 타입이나 개수는 건들면 안된다. 

- preHandle 메소드에 빨간 줄이 뜬다. default에서 public으로 수정하라고 뜬다.

인터페이스를 구현할 때 default 키워드는 사용할 수 없다.

오버라이딩이어도 접근제한자는 수정가능하다. 부모보다 더 크게는 가능하다. default에서 public으로 수정한다. 

 

 

- preHandle 메소드의 반환형이 boolean이라 true나 false를 반환해줘야 한다.

true를 리턴하면 원래 실행하려하던 컨트롤러가 쭉 이어서 실행된다.

false를 리턴하면 컨트롤러가 실행되지 않는다.

 

- preHandle 메소드의 매개변수를 보면 요청과 관련된 객체인 request와 응답과 관련된 객체인 response가 있다.

request가 있으면 session을 꺼낼 수 있다. 

HttpSession session = request.getSession();을 작성한다.

 

 

- redirect가지고 문자열 반환 아니다. boolean반환형이다.

response.sendRedirect()로 url을 재요청한다.

- 포워딩이 아니고 url 재요청(리다이렉트)이기 때문에 RedirectAttributes에 alert 메세지를 담았었다.

근데 그건 컨트롤러측 메소드에 매개변수를 추가해서 이용했었다.

지금은 오버라이딩한 메소드이기 때문에 함부로 매개변수를 추가하면 안된다.

- 그럼 지금 있는걸 가지고 RedirectAttributes를 대체할만한 무언가를 이용해야 한다.

 

 

 

 

 

ㅁ 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>
 
 
</beans:beans>
 

 

 

- 웹소켓 관련 등록 구문 아래에 인터셉터 관련 등록 구문을 추가한다.

- 인터셉터 클래스를 여러개 만들고 여러개 등록할 수도 있다. 

interceptors 안에 interceptor 태그를 여러개 두면 된다.

 

 

 

 

 

ㅁ 서버 start

 

 

- 로그인하지 않은 상태로 url을 써서 이동을 요청하면 alert가 뜨고 메인페이지(http://localhost:8888/spring/)로 이동된다.

- 로그인 후에는 잘 가진다.

 

 

'Spring' 카테고리의 다른 글

[스프링 부트] migration  (2) 2024.11.05
[스케줄러]  (2) 2024.11.05
[웹소켓] 2.  (2) 2024.11.04
[웹소켓] 1.  (0) 2024.11.04
[웹프로젝트] 20. 게시글 수정  (1) 2024.10.31