# Spring Security - 기본 API 및 Filter [2]

uuuu.jini·2022년 2월 18일
0

Spring Security

목록 보기
2/5
post-thumbnail

🐯Logout 처리, LogoutFilter

Logout API

클라이언트가 로그아웃 요청을 하면 스프링 시큐리티가 요청을 받아서 로그아웃 처리를 한다. ( 세션 무호화 , 인증토큰(객체) 삭제 , securityContext객체 삭제, 쿠키정보 삭제, 로그인 페이지로 리다이렉트 )

http.logout()

로그아웃 기능이 작동한다.

  • .logoutUrl : 로그아웃 처리 Url , 폼태그에서 액션 url정보를 변경할 수 있다 .( UI쪽도 동일 변경)
  • .logoutSuccessUrl("/login") : 로그아웃 성공 후 이동 페이지
  • .deleteCookies("...","...") : 로그아웃 후 쿠키 삭제
  • .addLogoutHandler(logoutHandler()) : 로그아웃 핸들러, 로그아웃 시 스프링 시큐리티가 기본으로 제공하는 구현체가 있으며, 우리가 별도로 처리를 하고 싶을 때 인터페이스를 구현하여 설정해주면 핸들러가 호출되어 해당 내용들의 처리가 가능하다.
  • logoutSucessHandler(logoutSuccessHandler()) : 로그아웃 성공 후 후속작업을 위한 핸들러 ( 인터페이스를 구현한 클래스를 만들어서 설정해주면 해당 처리를 해주게 된다. )

LogoutFilter

logout 요청을 하게되면 LogoutFilter가 요청을 받아서 처리를 하게 된다.

  1. Logout요청시(post방식) LogoutFilter가 요청을 받는다.
  2. AntPathRequestmatcher("/logout") : 해당 사용자의 로그아웃 요청이 매칭이 되는지 검사를 하고 매칭이 되지 않은 경우 다음 필터로 이동하고 로그아웃을 하지 않는다. 매칭이 되면 로그아웃 필터가 SecurityContext 객체로 부터 인증 객체(Authentication 객체)를 꺼내온다.
  3. 로그아웃 핸들러에게 인증 객체를 전달하고 SecurityContextLogoutHandler세션 무효화,쿠키 삭제, SecurityContextHolder.clearContext() 를 수행한다. 인증객체도 null로 초기화한다. (get방식으로 로그아웃 처리시에도 securityContextLogoutHandler를 사용하여 처리가 가능하다. )
  4. 로그아웃 핸들러가 성공적으로 수행을 하면 SimpleUrlLogoutSuccessHandler 클래스를 호출하여 login 페이지로 이동하도록 처리가 된다.


🐯 Remember Me 인증

설정 페이지에서 remember me를 활성화 시키면 로그인 페이지에서 Remember me on this computer라는 추가기능을 제공해준다. 쿠키에 저장이 되고 해당 쿠키를 가지고 서버에 계속해서 접근을 하게 된다.

  1. 세션이 만료되고 웹 브라우저가 종료된 후에도 어플리케이션이 사용자를 기억하는 기능
  2. Remember-Me 쿠키에 대한 Http요청을 확인한 후 토큰 기반 인증을 사용해 유효성을 검사하고 토큰이 검증되면 사용자는 로그인 된다.
  3. 사용자 라이프 사이클 : 인증성공 (remember-me 쿠키 설정) , 인증 실패(쿠키가 존재하면 쿠키 무효화) , 로그아웃(쿠키가 존재하면 쿠키 무효화 )

Remember-me API

http.rememberMe()

rememberMe 기능이 작동함

  • .rememberMeParameter("remember") : 기본 파라미터 명은 remember-me , 파라미터명의 변경이 가능하다. 사용자 화면의 체크박스의 파라미터 명 (이름) 과 일치해야 한다.
  • .tokenValiditySeconds(3600) : 리멤버미 쿠키의 만료시간 설정가능 , 기본 14일 , 초단위
  • .alwaysRemember(true) : 기본값 false,리멤버 미 기능이 활성화되지 않아도 항상 실행 ( 체크하지 않아도 인증 되면 항상 활성화 )
  • .userDetailsService(userDetailsService) : 리멤버미 기능 실행시 시스템에 있는 사용자 계정을 조회할때 필요한 클래스이다. ( 꼭 필요한 설정이다. )

리멤버미 기능을 활성화하여 사용자가 인증을 받으면 리멤버미 쿠키에 해당 사용자 인증이 저장된다. ( 세션이 삭제되도 재인증이 필요하지 않다. )


🐯 Remember Me 인증 필터 : RemembermeAuthenticationFilter

필터가 사용자 요청을 받아서 처리하는 조건이 있다. 첫번째는 Authentication 객체가 null일 경우 해당 filter가 동작한다. (인증객체가 securityContext객체에 저장되어 있는데 존재하지 않는 경우는 사용자 세션이 만료되었거나 세션이 끊겨져서 더이상 세션안에서 securityContext를 찾지못하고 존재하지않기 때문에 인증객체가 없는 경우이다. ) null이 아닌경우에는 필터가 동작하지 않는다. ( 이미 인증이 완료되어있으므로 다시 인증 받을 필요가 없다. 인증을 받은 사용자가 세션 timeOut이거나 브라우저가 종료되어서 세션 끊긴경우 인증 유지위해서 필터가 인증을 시도하는 것이다. )

두번 째는 , 사용자가 최초의 form인증을 받을 당시 리멤버기능 활성화하여 리멤버미 쿠키를 발급받고, 세션은 무효화 되었지만 다시 서버 접속시 request헤더에 리멤버미 쿠키값을 가지고 요청하는 경우 리멤버미 쿠키를 사용하여 인증을 시도하고 이때 필터가 동작한다.

  1. 세션이 만료된 사용자가 리멤버미 쿠키를 가지고 요청할 경우 필터는 동작하며 RememberMeServices 인터페이스의 구현체인 TokenBasedRememberMeServices와 PersistentTokenBasedRememberMeServices 가 실제 리멤버미 인증 처리를 하는 클래스이다. ( TokenBasedRememberMeService - 메모리에서 실제로 저장한 토큰과 요청떄 가져온 쿠키와 비교하여 인증처리를 한다. 14일 만료기간이 있다. PersistentTokenBasedRememberMeServices - 영구적인 방식으로 db에 토큰을 저장하고 토큰을 가지고 온 클라이언트의 값과 디비의 값을 비교하여 인증처리를 하는 클래스이다. )

  2. Token Cookie를 추출한 후 Token이 존재하지 않으면 다음 필터로 이동한다. Token이 존재하면 해당 토큰이 규칙을 지킨 포맷인지 확인하고 정상이 아닌경우 예외를 발생하고 정상인 경우 token이 서로 일치하는지를 비교한다. 서로 일치하지 않으면 예외 일치하면 계정이 존재하는 지를 확인한다. 존재하지않으면 예외, 존재하는 경우 새로운 Authentication 을 생성하고 AuthenticationManager에게 전달하여 실제 인증처리를 하게 된다.

즉, 리멤버미 쿠키가 대신해서 인증처리를 해줌으로써 세션이 만료되어도 인증을 유지해주는 기능이라고 생각하면 된다.

🐯 익명사용자 인증 필터 : AnonymousAuthenticationFilter

어떤 사용자가 인증을 받게 되면 세션에 인증을 받은 사용자의 객체를 저장한다. 저장한 후 이 사용자가 어떤 자원에 접근하려고 하면 세션에서 인증객체가 존재하는지 아닌지를 판단하여서 자원에 접근 여부를 결정한다. 보통 인증된 사용자와 인증되지 않은 사용자를 구분한다. 이 필터는 인증을 받지 않은 사용자를 null로 처리하는 것이 아닌 별도의 익명 사용자용 인증 객체를 만들어서 사용한다.

사용자의 요청을 필터가 받으면 처음에는 요청하는 사용자의 인증객체가 존재하는지 아닌지를 판단한다. 인증 객체가 존재한다면 다음 필터를 실행하고 인증객체가 존재하지 않는다면 ( 인증을 받지 않음 ) 익명 인증 객체( AnonymousAuthenticationToken )를 생성하여 Security Context에 저장한다.

  • 익명 사용자 인증 처리 필터
  • 익명사용자와 인증 사용자를 구분해서 처리하기 위한 용도로 사용
  • 화면에서 인증 여부를 구현할 때 isAnonymous()isAuthenticated() 로 구분해서 사용 (null로 구분이 아닌 익명사용자로 구분하기 위해 사용하는 필터이다. )
  • 인증객체를 세션에 저장하지 않는다. ( 사용자가 인증객체를 가지고 있어도 실제로는 인증을 받지 않은 사용자이다. )

🐯 동시 세션 제어, 세션 고정 보호, 세션 정책

동시 세션 제어

현재 동일한 계정으로 인증을 받을 때 생성되는 세션의 허용 개수가 초과되었을 경우 세션을 어떻게 초과하지 않고 유지하는지에 대한 제어이다. 스프링 시큐리티에서는 두가지 전략을 제공한다.

만약 최대 세션 허용 개수를 초과하였다고 가정한다. (최대 세션 허용 개수 : 1개)

  1. 이전 사용자 세션 만료 : 서버에 이전에 접속한 사용자의 세션을 만료시킨다. 최근에 사용한 사용자의 세션이 유지된다.

  2. 현재 사용자 인증 실패 : 서버에 이후에 접속한 사용자의 인증을 실패시킨다. 이전 사용자의 세션이 유지된다.

동시 세션 제어 API - http.sessionManagement()

세션 관리 기능이 작동한다. 동시 세션 제어 뿐만 아니라 여러가지 기능을 제공한다.

  • .maximumSessions(1) : 최대 허용 가능한 세션 수 이다. ( -1 : 무제한 로그인 세션 허용 )
  • .maxSessionsPreventsLogin(true) : 동시 로그인을 차단한다. 세션이 생성하지 못하게 한다. ( false : 기존 세션 만료 ,default ) 최근 사용자의 인증을 실패하게 한다. -- true
  • .invalidSessionUrl("/invalid") : 세션이 유효하지 않을 때 이동할 페이지(우선)
  • .expiredUrl("/expired") : 세션이 만료된 경우 이동 할 페이지

세션 개수 초과시 나오는 기본 화면
1. maxSessionPreventsLogin이 true인 경우 이후 사용자의 인증을 실패시킨다.

2. false인 경우 이전 사용자의 세션을 만료시킨다.

세션 고정 보호

공격자가 서버에 접속을 하면 서버는 세션아이디(쿠키)를 발급한다. 이 상태에서 공격자는 해당 쿠키를 사용자에게 심어놓는다. 사용자는 이 세션 쿠키로 로그인을 시도한다. 인증시 세션아이디 쿠키로 접근하고 쿠키에 해당하는 세션이 인증받은 상태이기 때문에 서버가 사용자나 공격자나 동일한 쿠키로 접근시 두 사용자 모두가 세션을 공유하게 된다. 그렇기 때문에 공격자는 인증이 되지 않아도 해당 쿠키를 사용하면 마치 사용자가 인증받은 것처럼 공격자도 인증받은 사용자로 모든 사용자의 정보를 공유하게 된다. -- 세션 고정 공격 이다.

이 공격을 방지하기 위하여 세션 고정 보호라는 기능을 스프링 시큐리티가 제공하는 것이다. 사용자가 공격자가 심어놓은 쿠키로 접속하여 인증을 시도하더라도 인증할때마다 새로운 세션아이디를 생성하여 사용자에게 돌려준다. -- 공격자가 기존의 세션아이디로 접속하여도 사용자와 세션을 공유할 수 없게 된다. 즉, 인증에 성공시마다 새로운 세션아이디가 발급되도록 처리를 해주는 것이 세션 고정 보호 이다.

세션 고정 보호 API - http.sessionManagement()

세션 관리 기능이 작동한다.

  • .sessionFixation().changeSessionId() : 기본값이다. 사용자가 인증을 성공하게 되면 세션은 그대로 두고 세션 아이디만 변경이 된다. 공격자가 사용자의 세션을 공유할 수 없다. (세션id를 모름) migrateSession - 세션 id 새로 발급, 서블릿 3.1이하에서 작동하는 속성이다. 설정 유지된다. , newSession - 세션이 새롭게 생성 & 세션 id도 재발급, 기존 속성값들도 새롭게 설정해야 한다. none - 세션 id가 새로 생성되지 않는다. 세션 고정 공격에 취약하다.

세션 정책 API - http.sessionManagement()

세션 관리 기능이 작동한다.

  • .sessionCreationPolicy(SessionCreationPolicy.If_Required) : Always - 스프링 시큐리티가 항상 세션을 생성한다. If_Required - 필요시 생성한다.(기본값) Never - 생성하지 않고 이미 존재하면 사용한다. Stateless - 생성하지 않고 존재해도 사용하지 않는다.
profile
멋쟁이 토마토

0개의 댓글