Spring Security - 1

이재현·2024년 8월 29일

Spring

목록 보기
11/13

🤍 Spring Security

Spring Security는 스프링 기반의 애플리케이션 보안(인증과 권한)을 담당하는 프레임워크이다.
Filter 기반으로 동작하기 때문에 스프링 MVC와 분리되어 관리 및 동작한다.

Filter는 Dispatcher servlet으로 가기 전에 적용됨으로 가장 먼저 URL 요청을 받지만, Interceptor는 Dispatcher와 Controller 사이에 위치한다. 따라서 이 둘은 적용 시점이 다르다.


🩵 Spring Security Filter

스프링 MVC에서 요청을 가장 먼저 받는 것이 DispatcherServlet이다.
그리고 이 요청을 받기 전에 다양한 필터가 있을 수 있다.

💙 Security Filter Chain

Spring Security는 다양한 기능을 가진 필터들을 10개 이상 기본적으로 제공하고 있다.
이렇게 제공되는 필터들을 Security Filter Chain이라고 한다.




🩵 Spring Security 주요 모듈

💙 Authentication

현재 접근하는 주체의 정보와 권한을 담는 인터페이스이다.

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

💙 SecurityContext

Authentication을 보관하는 역할을 하며, SecurityContext를 통해서 Authentication 객체를 꺼내 올 수 있다.

💙 SecurityContextHolder

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

이쯤에서 절차를 한번 살펴보자.

  1. 유저가 로그인을 통해 인증을 마친다.

  2. 인증에 성공하면 principal과 credential 정보를 Authentication에 담는다.

  3. SpringSecurity에서 Authentication을 SpringContext에 보관한다.

  4. SpringContext을 SecurityContextHolder에 담아 보관한다.

이런 느낌으로 위 3가지 모듈이 연관관계를 맺고 있다.


💙 UserDetails

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

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

이걸 가지고 현재 프로젝트에서 별도의 Details로 구현할 수 있다.

public class CustomUserDetails implements UserDetails {
	private User user;
	public User getUser() {
	return user;
}
public CustomUserDetails(User account) {
	this.user = account;
}
@Override
// 기타 등등 메서드 구현
}

💙 UserDetailsService

UserDetailsService는 UserDetails 객체를 반환하는 하나의 메서드만을 가지고 있다.
일반적으로 이를 implements한 클래스에 UserRepository를 주입 받아서 DB와 연결하여 처리한다.
즉, 이곳에서 DB의 사용자 정보를 조회한다.

public interface UserDetailsService {
	UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;
}

이걸 현재 프로젝트에서 별도로 구현한 뒤에 프로젝트 구조에 맞게 변형시켜 사용하면 된다.


💙 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에 의해 처리된다.
이것을 implements 한 것이 ProviderManager이다.
인증에 성공하면 두 번째 생성자를 이용해 객체를 생성하여 SecurityContext에 저장한다.

💙 AuthenticationProvider

AuthenticationProvider에서는 실제 인증에 대한 부분을 처리한다.
인증 전의 Authentication 객체를 받아서 인증이 완료된 객체를 반환하는 역할을 한다.

0개의 댓글