Spring Security Internals -2

김재현·2022년 8월 20일
0

Programmers

목록 보기
21/28

세션 처리

SecurityContextPersistenceFilter

  • SecurityContextRepository 인터페이스 구현체를 통해 사용자의 SecurityContext를 가져오거나 갱신함
    • 인증 관련 필터 중 가장 최 상단에 위치 — 이미 인증된 사용자는 다시 로그인할 필요가 없음
    • SecurityContext가 존재하지 않는다면, empty SecurityContext를 생성함
  • SecurityContextRepository 인터페이스 기본 구현은 Session을 이용하는 HttpSessionSecurityContextRepository 클래스

SessionManagementFilter

  • 세션 고정 보호 (session-fixation protection)
    • session-fixation attack — 세션 하이재킹 기법중 하나로 정상 사용자의 세션을 탈취하여 인증을 우회하는 기법

  • 인증 전에 발급 받은 세션 ID가 인증 후에도 동일하게 사용되면 발생할 수 있음
  • 즉, 인증 전에 사용자가 가지고 있던 세션이 인증 후에는 사용되지 않도록 하면 해당 공격에 효과적으로 대응할 수 있음

  • 새로운 사용자가 로그인 되었을 때 기존 세션을 SessionAutheticationStrategy 인터페이스를 통해 세션을 새로 만든다.
  • 로그인 이후에는 새로 생성된 세션을 사용.
  • 악의적인 공격자가 이전에 갖고 있던 세션 아이디는 유효하지 않게 되고, 방어가 가능하다.
  • Spring Security에서는 4가지 설정 가능한 옵션을 제공함
    • none — 아무것도 하지 않음 (세션을 그대로 유지함)
    • newSession — 새로운 세션을 만들고, 기존 데이터는 복제하지 않음
    • migrateSession — 새로운 세션을 만들고, 데이터를 모두 복제함
    • changeSession — 새로운 세션을 만들지 않지만, session-fixation 공격을 방어함 (단, servlet 3.1 이상에서만 지원. 스프링 시큐리티에서 기본으로 사용하는 방법.)
  • 유효하지 않은 세션 감지 시 지정된 URL로 리다이렉트 시킴
  • 세션 생성 전략 설정
    • IF_REQUIRED — 필요시 생성함 (기본값)
    • NEVER — Spring Security에서는 세션을 생성하지 않지만, 세션이 존재하면 사용함
    • STATELESS — 세션을 완전히 사용하지 않음 (JWT 인증이 사용되는 REST API 서비스에 적합)
    • IF_REQUIRED — 필요시 생성함 (기본값)
    • ALWAYS — 항상 세션을 사용함
  • 동일 사용자의 중복 로그인 감지 및 처리
    • maximumSessions — 동일 사용자의 최대 동시 세션 갯수
    • maxSessionsPreventsLogin — 최대 갯수를 초과하게 될 경우 인증 시도를 차단할지 여부 (기본값 false)
@Override
protected void configure(HttpSecurity http) throws Exception {
  http
		/**
     * 세션 관련 설정
     */
    .sessionManagement()
      .sessionFixation().changeSessionId()
      .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
      .invalidSessionUrl("/")
      .maximumSessions(1)
	      .maxSessionsPreventsLogin(false)
				.and()
      .and()
  ;
}
  • AbstractAuthenticationProcessingFilter 객체는 SessionManagementFilter와 동일한 세션 고정 보호, 최대 로그인 세션 제어를 수행함
    • 위 두 개의 필터는 SessionAuthenticationStrategy 객체를 공유함
    • AbstractAuthenticationProcessingFilter 구현을 보면, 인증 처리가 완료 된 후 SessionAuthenticationStrategy 객체를 통해 필요한 처리를 수행하고 있음

인가 처리 (AccessDecisionManager)

인가(Authorization)

: 어플리케이션 보안을 이해하는데 두 번째로 중요한 핵신 개념으로(다른 하나는 인증) 권한이 부여된 사용자들만 특정 기능 또는 데이터에 접근을 허용하는 기능이다.
이를 위해 인가 처리는 두 개의 작업으로 구분된다.

  • 인증된 사용자와 권한을 매핑해야 함 > Spring Security에서는 보통 역할이라고 함 (예: ROLE_USER, ROLE_ADMIN, ROLE_ANONYMOUS)
  • 보호되는 리소스에 대한 권한 확인 > 관리자 권한을 가진 사용자만 관리자 페이지에 접근 가능

FilterSecurityInterceptor

  • 필터 체인 상에서 가장 마지막에 위치하며, 사용자가 갖고 있는 권한과 리소스에서 요구하는 권한을 취합하여 접근을 허용할지 결정함
    • 실질적으로 접근 허용 여부 판단은 AccessDecisionManager 인터페이스 구현체에서 이루어짐
  • 해당 필터가 호출되는 시점에서 사용자는 이미 인증이 완료되고, Authentication 인터페이스의 getAuthorities() 메소드를 통해 인증된 사용자의 권한 목록을 가져올수 있음
    • 익명 사용자도 인증이 완료된 것으로 간주하며, ROLE_ANONYMOUS 권한을 갖음
  • 보호되는 리소스에서 요구하는 권한 정보는 SecurityMetadataSource 인터페이스를 통해 ConfigAttribute 타입으로 가져옴

  • FilterSecurityInterceptor부터 인가처리 시작.
    SecurityContextHolder를 통해 인증된 사용자의 Authentication객체를 가져옴. 어선티케이션 객체는 사용자가 익명 사용자라면 AnonymousAuthenticationToken, 인증 완료됐다면 UsernameAuthenticationToken 또는 RemembermeAuthenticationToken일 것.
  • SecurityMetadataSource를 통해 사용자가 접근하려고 하는 리소스에서 요구하는 권한이 뭔지에 대한 정보를 ConfigAttributesType으로 가져옴. AccessDecisionManager(인터페이스 타입)를 호출. 액세스 디시젼 매니저의 구현체에는 세가지가 있음.
    디시젼 매니져가 Voter들을 통해 승인할지 거절할지 판단하고 구현체가 그 보터들의 판단결과를 취합해서 최종적으로 승인, 거절을 결정. 승인할 경우 사용자는 리소스에 접근할 수 있게 되고, 처리가 정상 종료됨. 만약 권한이 없어 거절당하면 엑세스 디나이드 익셉션 발생.ㅣ

AccessDecisionManager 인터페이스

  • 사용자가 갖고 있는 권한과 리소스에서 요구하는 권한을 확인하고, 사용자가 적절한 권한을 갖고 있지 않다면 접근 거부 처리함
  • AccessDecisionVoter 목록을 갖고 있음
  • AccessDecisionVoter들의 투표(vote)결과를 취합하고, 접근 승인 여부를 결정하는 3가지 구현체를 제공함
    • AffirmativeBased — AccessDecisionVoter가 승인하면 이전에 거부된 내용과 관계없이 접근이 승인됨 (기본값)
    • ConsensusBased — 다수의 AccessDecisionVoter가 승인하면 접근이 승인됨
    • UnanimousBased — 모든 AccessDecisionVoter가 만장일치로 승인해야 접근이 승인됨

AccessDecisionVoter 인터페이스

  • 각각의 AccessDecisionVoter는 접근을 승인할지 거절할지 혹은 보류할지 판단함 (vote 메소드)
    • ACCESS_GRANTED — 접근 승인
    • ACCESS_DENIED — 접근 거부
    • ACCESS_ABSTAIN — 판단 보류 (판단을 위한 정보 부족 등)
int ACCESS_GRANTED = 1;
int ACCESS_ABSTAIN = 0;
int ACCESS_DENIED = -1;

int vote(Authentication authentication, S object, Collection<ConfigAttribute> attributes);

WebExpressionVoter 구현체

  • SpEL 표현식을 사용해 접근 승인 여부에 대한 규칙을 지정할 수 있음
  • SpEL 표현식 처리를 위해 DefaultWebSecurityExpressionHandler 그리고 WebSecurityExpressionRoot 구현에 의존함
    • DefaultWebSecurityExpressionHandler.createSecurityExpressionRoot() 메소드에서 WebSecurityExpressionRoot 객체를 생성함
  • WebSecurityExpressionRoot 클래스는 SpEL 표현식에서 사용할수 있는 다양한 메소드를 제공

0개의 댓글