[GO SOPT 서버] Spring Security, 어노테이션 정리

ddongseop·2023년 6월 22일
0

GO SOPT 서버파트 6차 세미나 과제입니다.

  • Spring Security 정리
  • 새롭게 사용한 어노테이션 정리

⭐️ Spring Security 동작 과정 정리

Spring Security는 Spring 기반의 애플리케이션에서 인증(Authentication)과 인가(Authorization)을 도와주는 프레임워크로, 보안 관련된 로직을 개발자가 하나하나 작성하지 않아도 되므로 편리하다.

🔥 인증(Authentication) vs 인가(Authorization)

  • 인증(Authentication): 아이디와 비번이 일치하는지 확인
  • 인가(Authorization): 인증된 사용자가 요청 자원에 접근할 수 있는 권한이 있는지 확인

🔥 Principal 과 Credential

  • Spring Security는 인증과 인가를 위해 Principal (접근 주체)를 아이디로, Credential을 비밀번호로 사용하는 Credential 기반의 인증 방식을 사용한다!

🔥 필터(Filter)의 흐름에 따라 처리

  • Client (request) → Filter → DispatcherServlet → Interceptor → Controller

Filter는 Dispatcher Servlet으로 가기 전에 적용되므로 가장 먼저 URL 요청을 받지만, Interceptor는 Dispatcher Servlet과 Controller 사이에 위치한다는 점에서 적용 시기가 다르다!
Filter는 웹 컨테이너❗️에서 관리하지만, Interceptor는 스프링 컨테이너❗️에서 관리한다는 차이가 존재
Filter에서 하는 이유도, 스프링 컨테이너까지 전달되지 않도록 방지 ❗️하여 보안을 지키기 위함이다.

  1. 사용자가 로그인 정보와 함께 인증 요청을 한다.(Http Request)
  2. AuthenticationFilter가 요청을 가로채고, 가로챈 정보를 통해 UsernamePasswordAuthenticationToken의 인증용 객체를 생성한다.
  3. AuthenticationManager의 구현체인 ProviderManager에게 ⭐️생성한 UsernamePasswordToken 객체를 전달⭐️한다.
  4. AuthenticationManager는 등록된 AuthenticationProvider(들)을 조회하여 인증을 요구한다.
  5. ⭐️실제 DB에서 사용자 인증정보를 가져오는 UserDetailsService에 사용자 정보를 넘겨준다.
  6. 넘겨받은 사용자 정보를 통해 DB에서 찾은 사용자 정보인 UserDetails⭐️ 객체를 만든다.
  7. AuthenticationProvider(들)은 UserDetails를 넘겨받고 사용자 정보를 비교한다.
  8. 인증이 완료되면 권한 등의 사용자 정보를 담은 Authentication 객체를 반환한다.
  9. 다시 최초의 AuthenticationFilter에 ⭐️Authentication 객체⭐️가 반환된다.
  10. Authenticaton 객체를 SecurityContext에 저장한다.
    사용자 정보를 저장 = Spring Security는 전통적인 세션-쿠키 기반의 인증 방식을 사용

👻 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
	}
}

👻 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();

}

👻 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;
}

⭐️ 새롭게 사용한 어노테이션 정리

🔥 Custom Anntoatiaon

  • @interface을 붙여 어노테이션을 선언하고, @Target 어노테이션을 통해 적용될 대상을 지정하며,
    @Retention 어노테이션을 통해 적용될 범위를 지정할 수 있음
@Target(ElementType.PARAMETER)
@Retention(RetentionPolicy.RUNTIME)
public @interface UserId {
}

👻 @Target

  • @Target 어노테이션을 통해 적용될 대상을 지정할 수 있으며, 속성 목록은 아래와 같다.
ElementType적용 대상
TYPE클래스 및 인터페이스
FIELD클래스의 멤버 변수
METHOD메서드
PARAMETER파라미터
CONSTRUCTOR생성자
LOCAL_VARIABLE지역변수
ANNOTATION_TYPE어노테이션 타입
PACKAGE패키지
TYPE_PARAMETER타입 파라미터
TYPE_USE타입 사용

👻 @Retention

  • @Retention 어노테이션을 통해 어노테이션이 지정될 범위를 지정할 수 있으며, 속성 목록은 아래와 같다.
RetentionPolicy설명
RUNTIME컴파일 이후에도 참조 가능합니다
CLASS클래스를 참조할 때 까지 유효합니다
SOURCE컴파일 이후 어노테이션 정보가 소멸됩니다

👻 HandleMethodArgumentResolver

  • 해당 인터페이스는 컨트롤러 메서드에서 특정 조건에 맞는 파라미터가 있을 때, 원하는 값을 바인딩해주는 인터페이스
  • HandleMethodArgumentResolver 인터페이스를 구현하는 UserIdResolver를 생성하고, WebConfig에 추가해주면 어노테이션을 통해 유저 인증을 할 수 있음

0개의 댓글