2022년 5월 20일 TIL

yshjft·2022년 5월 20일
0

데브코스 TIL

목록 보기
35/45

Remember-Me 인증

RememberMeAuthenticationFilter

  • 자동 로그인 처리를 담당한다.
  • Remember-me를 위해 cookie 사용한다.
    • key(): remember-me 쿠키에 대한 고유 식별키 (미입력시 랜덤 텍스트)
    • rememberMeParameter(): remember-me 쿠키 파라미터명(default remember-me)
    • tokenValiditySeconds(): 쿠키 만료 시간 (초 단위)
    • alwaysRemember(): 항상 remember-me 를 활성화 시킴 (기본값 false)
http
	
    ...
    
	.rememberMe()
		.key("my-remember-me")
		.rememberMeParameter("remember-me")
		.tokenValiditySeconds(300)
		.alwaysRemember(false)
	  .and()
  • 실제 인증은 RememberMeServcies에서 인증 처리한다.

    • interface RememberMeServcies
    • abstract class AbstractRememberMeServices
      • implements RememberMeServices
      • autoLogin()
        • remember-me 쿠키를 인증하고 자동으로 인증을 처리(processAutoLoginCookie())한다.
        • 인증 성공 시 createSuccessfulAuthentication()을 통해 RememberMeAuthenticationToken을 생성
    • class TokenBasedRememberMeServices
      • extends AbstractRememberMeServices
      • MD5 해시 알고리즘을 기반으로 쿠키를 검증한다.
      • onLoginSuccess()
        쿠키(username, 만료 시각, signature value)가 생성된다.
    • class PersistentTokenBasedRememberMeServices
      • extends AbstractRememberMeServices
      • 외부 데이터베이스에서 인증에 필요한 데이터를 가져오고 검증한다.
      • 인증 시 마다 매번 갱신되는 임의의 토큰 값을 사용하여 보다 높은 보안성을 제공한다.
  • RememberMeAuthenticationToken

    • interface Authentication
    • abstract class AbstractAuthenticationToken
      • implements Authentication
    • class RememberMeAuthenticationToken
      • extends AbstractAuthenticationToken
      • remember-me 기반 Authentication 인터페이스 구현체
      • 언제나 인증이 완료된 상태로만 존재한다.
  • RememberMeAuthenticationFilter.authenticationManager.authenticate(rememberMeAuth)

    • RememberMeAuthenticationProvider.authenticate(rememberMeAuth)
    • RememberMeAuthenticationToken을 처리한다.
    • key 값을 비교한다.
  • 인증 완료되면 인증 토큰을 스레드 로컬 변수에 저장

  • 참고) isFullyAuthenticated()

http
                .authorizeRequests()
                    .antMatchers("/admin").access("isFullyAuthenticated() and hasRole('ADMIN')")

명시적으로 아이디/패스워드 입력을 한 경우에만 true를 반환한다.

SecurityContextPersistenceFilter

  • SecurityContextRepository 인터페이스 구현체를 통해 사용자의 SecurityContext를 가져오거나 갱신한다.

    • 인증 관련 필터 중 가장 최 상단에 위치
      이를 통해 이미 인증된 사용자는 다시 로그인할 필요가 없다.
    • 여기에서는 SecurityContext를 로드하고 저장하는 것이 핵심이다.
      • securityContext 로드 및 저장시 SecurityContextRepository를 사용한다.
      • SecurityContextRepository의 경우 인터페이스고 HttpSessionSecurityContextRepository가 구현체다. 이를 통해 SecurityContext가 세션에 기반해서 처리된다는 것을 알 수 있다.

SessionManageMentFilter

세션 고정 보호 (session-fixation protection)

  • session-fixation attack
    • 공격자가 사이트에 접속하여 세션을 얻은 후 XSS 등의 방법을 이용하여 얻은 세션을 일반 사용자에게 주입하고 일반 사용자가 로그인하였을 때 해당 세션을 이용하여 공격하는 방법
    • 세션 하이재킹 기법중 하나로 정상 사용자의 세션을 탈취하여 인증을 우회하는 기법
  • 인증 전에 사용자가 가지고 있던 세션이 인증 후에는 사용되지 않도록 하여 공격에 대응한다.
  • 4가지 옵션
    http.sessionManagement()
                        .sessionFixation().changeSessionId()
    • none(): 세션을 그대로 유지, 사용할 일 없을 듯
    • newSession(): 새로운 세션을 만들되 기존 데이터는 복제하지 않는다
    • migrateSession(): 새로운 세션을 만들고 기존 데이터 모두 복제한다
    • changeSessionId(): 새로운 세션을 만들지 않지만 session-fixation 공격을 방어한다.(servlet 3.1 이상에서만 지원하며 기본으로 사용하고 있다)

유효하지 않은 세션 감지 시 지정된 URL로 리다이렉트 시킴

http.invalidSessionUrl("/")

세션 생성 전략 설정

http.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
  • IF_REQUIRED: 필요시 생성함 (기본값)
  • NEVER: Spring Security에서는 세션을 생성하지 않지만, 세션이 존재하면 사용함
  • STATELESS: 세션을 완전히 사용하지 않음 (JWT 인증이 사용되는 REST API 서비스에 적합)
  • ALWAYS: 항상 세션을 사용함

동일 사용자의 중복 로그인 감지 및 처리

http.maximumSessions(1)
                        .maxSessionsPreventsLogin(false)
                        .and()
  • maximumSessions: 동일 사용자의 최대 동시 세션 갯수
  • maxSessionsPreventsLogin: 최대 갯수를 초과하게 될 경우 인증 시도를 차단할지 여부 (기본값 false)

AbstractAuthenticationProcessingFilter

  • UsernamePasswordAuthenticationFilter
    • extends AbstractAuthenticationProcessingFilter
  • SessionManagementFilter와 동일한 세션 고정 보호, 최대 로그인 세션 제어를 수행한다.

인가

  • 인증된 사용자와 권한을 매핑해야 함(ex. ROLE_USER, ROLE_ADMIN, ROLE_ANONYMOUS)
  • 보호되는 리소스에 대한 권한 확인

FilterSecurityInterceptor

  • extends AbstractSecurityInterceptor
  • 사용자의 권한과 리소스에서 요구하는 권한을 비교하여 승인 여부를 결정한다.
  • 사용자의 인증 처리는 무조건 끝나 있는 상태이다.(익명 사용자도 인증이 완료된 것으로 인정한다)
    • ex) ROLE_ANONYMOUS, ROLE_USER
  • 보호되는 리소스에서 요구하는 권한 정보는 SecurityMetadataSource에서 FilterInvoation을 통해 ConfigAttribute 타입으로 가져온다.

AccessDiecisioinManager

  • interface
  • AbstractAccessDecisionManager가 해당 인터페이스를 구현
    • Voter(AccessDecisionVoter)들을 틍해 승인 여부를 결정한다.
    • 아래 클래스들이 AbstractAccessDecisionManager를 상속하고 있다.
      • UnanimousBased: AccessDecisionVoter들 중 하나라도 승인하면 이전에 거부된 내용과 관계없이 접근이 승인된다. (기본값)
      • ConsensusBased: 다수의 AccessDecisionVoter가 승인하면 접근이 승인된다.
      • AffirmativeBased: 모든 AccessDecisionVoter가 만장일치로 승인해야 접근이 승인된다.
  • 사용자가 갖고 있는 권한과 리소스에서 요구하는 권한을 확인하고, 사용자가 적절한 권한을 갖고 있지 않다면 접근 거부 처리한다.

AccessDecisionVoter

  • interface

  • 각각의 AccessDecisionVoter는 접근을 승인할지 거절할지 혹은 보류할지 vote 메서드를 통해 판단한다.

    • ACCESS_GRANTED: 접근 승인
    • ACCESS_DENIED: 접근 거부
    • ACCESS_ABSTAIN: 판단 보류 (판단을 위한 정보 부족 등)
WebExpressionVoter
  • AccessDecisionVoter의 기본 구현체
  • SpEL 표현식을 사용해 접근 승인 여부에 대한 규칙을 지정할 수 있다.
    • SpEL 표현식 처리를 위해 DefaultWebSecurityExpressionHandler와 WebSecurityExpressionRoot를 이용한다.
      DefaultWebSecurityExpressionHandler.createSecurityExpressionRoot() 메소드에서 WebSecurityExpressionRoot 객체를 생성한다.
      SecurityExpressionHandler<FilterInvocation> expressionHandler = new DefaultWebSecurityExpressionHandler();
    • WebSecurityExpressionRoot 클래스는 SpEL 표현식에서 사용할수 있는 다양한 메소드를 제공한다.
      • hasAnyRole(String… roles)
      • permitAll
      • isFullyAuthenticated()
profile
꾸준히 나아가자 🐢

0개의 댓글