어 나 갱수.

[SpringBoot] Spring Security란? 👏🏿 본문

Spring

[SpringBoot] Spring Security란? 👏🏿

김경수 2023. 9. 2. 12:20
728x90

대부분의 시스템에서는 회원 서비스가 존재한다. 그래서 그 회원에 대한 인증 인가 처리를 꼭 해주어야 한다.

SpringBoot에서는 이런 인증 인가처리를 SpringSecurity에서 처리하고 관리해 준다.

오늘은 이 SpringSecurity에 대해 알아보도록 하겠습니다.

 

Spring Security란?

Spring Security는 Spring 기반의 애플리케이션의 보안(인증, 인가)을 담당하는 스프링 하위 프레임워크입니다.

Spring Security는 Filter 흐름에 따라 인증 인가 처리를 하고 있습니다.

Spring Security는 인증 인가 처리 말고도 보안 관련된 다양하고 체계적인 옵션을 많이 제공해서 개발자가 보안적인 부분을 직접 신경 쓸 필요가 없다는 큰 장점도 있습니다.

인증(Authentication)과 인가(Authorization)

Spring Security에 대해 공부해 보기 전에 인증과 인가에 대해 한 번 더 정리해 보겠습니다.

  • 인증(Authentication) : 시스템을 이용하는 사용자가 본인이 맞는지 확인하는 절차
  • 인가(Authorization) : 시스템을 이용하는 사용자가 접근할 수 있는 권한이 있는지 확인하는 절차

Spring Security는 기본적으로 인증을 통해 사용자 본인을 확인하고, 인가를 통해 사용자에게 접근권한이 있는지 확인합니다.

Spring Security에서는 이러한 인증과 인가를 위해 Principal을 아이디로, Credential을 비밀번호로 사용하는 Credential 기반 인증 방식을 사용한다. 

  • Principal : 보호받는 리소스에 접근하는 주체
  • Credential : 보호받는 리소스에 접근하는 주체의 비밀번호

Spring Security 모듈

Authentication

현재 접근하는 주체의 권한을 담는 인터페이스이다. Authentication은 SecurityContext에 저장되며 SecurityContextHolder를 통해 SecurityContext에 접근할 수 있고 SecurityContext를 통해 Authentication에 접근할 수 있다.

public interface Authentication extends Principal, Serializable {
	// 현재 사용자의 권한 목록을 가져옴
	Collection<? extends GrantedAuthority> getAuthorities();
    
	// credentials(주로 비밀번호)을 가져옴
	Object getCredentials();
    
	Object getDetails();
 
	// Principal 객체를 가져옴
	Object getPrincipal();
 
	// 인증 여부를 가져옴
	boolean isAuthenticated();
    
	// 인증 여부를 설정함
	void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
 
}

UsernamePasswordAuthenticationToken

UsernamePasswordAuthenticationToken은 Authentication을 implements 한AbstractAuthenticationToken의 하위클래스로 User의 ID가 Principal 역할을 하고, Password가 Credential의 역할을 한다. UsernamePasswordAuthenticationToken의 첫 번째 생성자는 인증 전의 객체를 생성하고, 두 번째는 인증이 완료된 객체를 생성한다.

public abstract class AbstractAuthenticationToken implements Authentication, CredentialsContainer {
}
 
public class UsernamePasswordAuthenticationToken extends AbstractAuthenticationToken {
 
	private static final long serialVersionUID = SpringSecurityCoreVersion.SERIAL_VERSION_UID;
 
	// 주로 사용자의 ID에 해당
	private final Object principal;
 
	// 주로 사용자의 PW에 해당
	private Object credentials;
 
	// 인증 완료 전의 객체 생성
	public UsernamePasswordAuthenticationToken(Object principal, Object credentials) {
		super(null);
		this.principal = principal;
		this.credentials = credentials;
		setAuthenticated(false);
	}
 
	// 인증 완료 후의 객체 생성
	public UsernamePasswordAuthenticationToken(Object principal, Object credentials,
			Collection<? extends GrantedAuthority> authorities) {
		super(authorities);
		this.principal = principal;
		this.credentials = credentials;
		super.setAuthenticated(true); // must use super, as we override
	}
}

AuthenticationManager

AuthenticationManager을 통해서 인증에 대한 처리를 하는데 실질적으로는 AuthenticationManager에 등록된 AuthenticationProvider를 통해 인증이 처리된다. 인증에 성공하면 두번째 생성자를 통해 SecurityContext에 저장이 된다.

public interface AuthenticationManager {
 
	Authentication authenticate(Authentication authentication) throws AuthenticationException;
 
}

AuthenticationProvider

AuthenticationProvider은 실제 인증에 대한 처리를 하는 인터페이스이다.

인증을 하기 전인 Authentication 객체를 받아서 인증이 완료된 객체를 반환하는 역할을 한다.

public interface AuthenticationProvider {
 
	Authentication authenticate(Authentication authentication) throws AuthenticationException;
 
	boolean supports(Class<?> authentication);
 
}

ProviderManager

AuthenticationManager를 implements 한 ProviderManager는 AuthenticationProvider를 구성하는 목록을 갖는다.

public class ProviderManager implements AuthenticationManager, MessageSourceAware, InitializingBean {
	
    public List<AuthenticationProvider> getProviders() {
		return this.providers;
	}
    
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {
		Class<? extends Authentication> toTest = authentication.getClass();
		AuthenticationException lastException = null;
		AuthenticationException parentException = null;
		Authentication result = null;
		Authentication parentResult = null;
		int currentPosition = 0;
		int size = this.providers.size();
        
        // for문으로 모든 provider를 순회하여 처리하고 result가 나올때까지 반복한다.
		for (AuthenticationProvider provider : getProviders()) { ... }
	}
}

UserDetails

인증에 성공하면 생성된 UserDetails 객체는 Authentication 객체를 구현한 UsernamePasswordAuthenticationToken을 생성하기 위해 사용된다. UserDetails는 implements 하여 처리할 수 있다.

public interface UserDetails extends Serializable {
 
	// 권한 목록
	Collection<? extends GrantedAuthority> getAuthorities();
 
	String getPassword();
 
	String getUsername();
 
	// 계정 만료 여부
	boolean isAccountNonExpired();
 
	// 계정 잠김 여부
	boolean isAccountNonLocked();
 
	// 비밀번호 만료 여부
	boolean isCredentialsNonExpired();
 
	// 사용자 활성화 여부
	boolean isEnabled();
 
}

SecurityContextHolder

SecurityContextHolder는 보안 주체의 세부 정보를 포함하여 응용프로그램의 현재 보안 콘텍스트에 대한 세부 정보가 저장된다.

SecurityContext

Authentication을 보관하는 역할을 하며, SecurityContext를 통하여 Authentication에 접근할 수 있다.

SecurityContextHolder.getContext().setAuthentication(authentication);
SecurityContextHolder.getContext().getAuthentication(authentication);

GrantAuthority

GrantAuthority는 현재 사용자가 가지고 있는 권한을 의미합니다.

GrantAuthority는 UserDetailsService를 통해 불러올 수 있고, 특정 자원에 대한 권한이 있는지 검사하여 접근 허용 여부를 결정한다.


Reference

728x90