Search

Spring활용 - 쿠키,세션,필터,인터셉터

쿠키 & 세션

쿠키는 로그인할 때 잘 안쓴다!

대안

쿠키에 중요한 값을 노출하지 않고, 사용자 별로 예측 불가능한 임의의 토큰을 노출하고, 서버에서 토큰과 사용자 id를 매핑해서 인식한다. 서버에서 토큰을 관리
토큰은 해커가 임의의 값을 넣어도 찾을 수 없도록 예상 불가능해야한다.
해커가 토큰을 털어가도 시간이 지나면 사용할 수 없도록 서버에서 해당 토큰의 만료시간을 짧게 유지한다. 해킹이 의심되는 경우 서버에서 해당 토큰을 강제로 제거하면 됨

세션

동작 방식

세션 저장소를 만들고 거기서 세션을 관리함
해당 세션 id를 반환하는 식으로 동작

보안 문제 해결

쿠키 값을 변조 가능 → 예상 불가능한 복잡한 세션id를 사용한다.
쿠키에 보관하는 정보는 클라이언트 해킹시 털릴 가능성이 있다, → 세션 id가 털려도 여기에는 중요한 정보가 없다
쿠키 탈취 후 사용 → 해커가 토큰을 털어가도 시간이 지나면 사용할 수 없도록 서버에서 세션의 만료시간을 짧게 유지한다. 해킹이 의심되는 경우 서버에서 해당 세션을 강제로 제거

세션 만들기

기능

세션 생성 - sessionId 생성, 세션 저장소에 보관할 값 저장, 응답 쿠키 생성해서 전달
세션 조회 - sessionId 쿠키의 값으로 , 저장소에 보관한 값 조회
세션 만료 - 세션 저장소에 보관한 sessionId와 값 제거
HttpSession 객체를 쓰면 편하다.
//세션 설정 HttpSession session = request.getSession(); session.setAttribute(SessionConst.LOGIN_MEMBER,loginMember); //세션 파괴 if(session != null){ session.invalidate(); } //세션 조회 Member loginMember = (Member) session.getAttribute(SessionConst.LOGIN_MEMBER); or public String homeLoginV3Spring(@SessionAttribute(name = SessionConst.LOGIN_MEMBER, required = false) Member loginMember, Model model){ if(loginMember == null){ return "home"; } model.addAttribute("member",loginMember); return "loginHome"; }
Java
복사

필터

HTTP 요청 → WAS →필터 → 서블릿 → 컨트롤러
필터는 특정 URL 패턴에 적용할 수 있다. /* 이라고 하면 모든 요청에 필터갖 ㅓㄱ용됨
필터는 체인으로 구성되는데, 중간에 필터를 자유롭게 추가할 수 있다.
로그를 남기는 필터 적용 → 로그인 여부를 체크하는 필터 적용하도록

필터 인터페이스

public interface Filter{ public default void init(FilterConfig filterConfig) throws ServletException{} public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException; public default void destroy(){} }
Java
복사
init(): 필터 초기화 메서드, 서블릿 컨테이너가 생성될 때 호출
doFilter(): 고객의 요청이 올 때마다 해당 메서드가 호출, 필터의 로직을 구현
destroy(): 필터 종료 메서드, 서블릿 컨테이너가 종료될 대 호출

필터로 로그 남기기

Filter 인터페이스를 구현한 클래스를 짜고, Override해주면 됨
init, doFilter, destroy 세 개를 구현하면 된다.
필터를 만들었으면, 스프링 부트에 등록해줘야한다.
이 때 FilterRegistrationBean을 사용해서 등록하면 됨.
setFilter(new LogFilteR()) - Filter를 등록하기
setOrder(1) - Filter Chain의 우선 순위 정하기
addUrlPatterns("/*") - 어떤 URL들에 의해서 남길건지.

필터로 인증 만들기

loginCheckFilter()를 만든다.
기능
whitelist를 작성해서 필터가 안 돌아가게끔
미인증 사용자는 로그인 화면으로 다시 돌아가는데, 이 때 로그인을 하면 원래 진입하려는 방향으로 가는 것

인터셉터

스프링 인터셉터

스프링 MVC가 제공하는 기술
HTTP요청 → WAS → 필터 → 서블릿 → 스프링 인터셉터 → 컨트롤러
스프링 인터셉터는 디스패처 서블릿과 컨트롤러 사이에서 컨트롤러 호출 직전에 호출
스프링 인터셉터에도 URL 패턴을 적용할 수 있는데, 서블릿 URL 패턴과는 다르고, 매우 정밀하게 설정 가능

스프링 인터셉터 인터페이스

public interface HandlerInterceptor { //컨트롤러 호출 전 default boolean preHandle(HttpServletRequest request, HttpServlet Response response, Object Handler)throws Exception {} //컨트롤러 끝난 후 default boolean postHandle(HttpServletRequest request, HttpServlet Response response, Object Handler, @Nullable ModelAndView modelAndView)throws Exception {} //view 반환 후 default boolean afterCompletion(HttpServletRequest request, HttpServlet Response response, Object Handler, @Nullable Exception ex)throws Exception {}
Java
복사

정상 상황

preHandle; 컨트롤러 호출 전 호출 - preHandler의 응답값이 true이면 다음 진행, false이면 더 진행 X
postHandle: 컨트롤러 호출 후에 호출 됨
afterCompletion: 뷰가 렌더링 된 이후에 호출

예외 발생 시

preHandle: 컨트롤러 호출 전에 호출
postHandle: 컨트롤러에서 예외가 발생하면 postHandle은 호출되지 않는다.
afterCompletion: afterCompletion은 항상 호출된다. 이 경우 예외를 파라미터로 받아서 어떤 예외가 발생했는지 로그로 출력 가능
afterCompletion은 예외가 발생해도 호출 됨
preHandler(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception{ String requestURI = request.getRequestURI(); if(handler instanceof HandlerMethod){ HandlerMethod hm = (HandlerMethod) handler; }
Java
복사
HandlerMethod
어떤 핸들러 매핑을 사용하느냐에 따라 핸들러 정보가 달라진다.
스프링을 사용하면 @Controller, @RequestMapping을 활용한 핸들러 매핑을 사용한다.
ResourceHttpRequetHandler
@Controller가 아니라 /resources/static와 같은 정적 리소스가 호출되는 경우
ResourceHttpRequestHandler가 핸들러 정보로 넘어오기 때문에 타입에 따라서 처리가 필요함.
스프링 인터셉터의 경우 메서드의 호출 시점이 완전히 분리되어있다.
두 메서드가 함께 쓰기 위한 변수를 사용하려면 request.setAttribute()를 이용해야한다.
이 인터셉터는 싱글톤으로 관리되기 때문에, 지역변수를 쓰면 위험함.

스프링의 URL경로

? : 한 문자 일치
* : 경로(/)안에서 0개 이상의 문자 일치
**: 경로 끝까지 0개 이상의 경로(/) 일치
{spring} : 경로(/)와 일치하고 spring이라는 변수로 캡처
{spring: [a-z]+} : regexp [a-z]+와 일치하고, "spring" 경로 변수로 캡처
{*spring} 경로가 끝날때까지 0개 이상의 경로(/)와 일치하고 spring이라는 변수로 캡처

ArgumentResolver

우선 ArgumentResolver란 무엇이냐
파라미터로 날라오는 변수들에 대해 공통적인 작업을 해주는 기능이다.
이런 기능을 컨트롤러마다 하려며 말이 안되니까...
어노테이션 생성
ArgumentResolver를 어노테이션에 대해서 처리하도록 설정
supportsParameter
resolverArgument