Java/SpringBoot

UserDetailsService, UserDetails, GrantedAuthority, SimpleGrantedAuthority, stream

dev.jelee 2024. 10. 28. 19:18

생각

관리자 페이지와 관리자 권한 설정, 부여에 대하여 수업을 듣는데 @Service 단에서 클래스를 만드는데 UserDetailsService 인터페이스를 상속받는 클래스로 만들었다. 설명을 해주셨지만 처음보는 인터페이스라 금방 까먹었다. 하하. 그래서 공부할 겸 정리해본다.

왜 이렇게 어렵냐.. ㅠ


UserDetailsService

  • UserDetailService는 Spring Security에서 사용자 정보를 가져오는데 사용되는 인터페이스이다.
  • 주요 역할은 애플리케이션의 사용자 정보를 제공한다.
  • 사용자의 인증과 권한 부여에 사용된다.
  • 사용자 정보 로드
    • UserDetailsService는 특정 사용자의 정보를 데이터베이스나 다른 저장소에서 가져오는 메서드를 정의한다. 주로 사용자의 이름(username)으로 해당 사용자의 세부 정보를 로드한다.
  • UserDetails 객체 반환
    • 사용자의 정보를 담고 있는 userDetails 객체를 반환한다. 이 객체는 사용자의 이름, 비밀번호, 권한 등의 정보를 포함하고 있다.
    • 여기서 UserDetails가 객체라는 것이 아니라 UserDetails는 인터페이스이고 이 인터페이스를 구현한 클래스의 인스턴스를 의미하는 것이다. 객체를 반환 = UserDetails의 인스턴스(객체)를 반환

UserDetails

  • Spring Security에서 사용자의 정보를 담고 있는 인터페이스다.
  • 인증(Authentication)과 인가(Authorization)을 위해 필요한 정보를 제공한다.
  • 사용자 정보 담기
    • UserDetails는 사용자의 기본 정보, 즉 사용자 이름, 비밀번호, 권한 등을 포함한다.
    • 이 정보는 로그인할 때 사용자가 인증되는 데 필요하다.
  • 인터페이스
    • UserDetails는 인터페이스이기 때문에, 이를 구현하는 클래스가 필요하다.
    • Spring Security는 User라는 기본 구현 클래스를 제공한다.
  • 메서드
    • UserDetails 인터페이스에는 여러 메서드가 정의되어 있다.
    • getUsername(): 사용자 이름 반환.
    • getPassword(): 비밀번호 반환.
    • getAuthorities(): 사용자의 권한 목록 반환
    • isAccountNonExpired(): 계정이 만료되지 않았는지 여부를 반환
    • isAccountNonLocked(): 계정이 잠겨 있지 않은지 여부를 반환
    • isCredentialsNonExpired(): 비밀번호가 만료되지 않았는지 여부를 반환
    • isEnabled(): 계정이 활성화되어 있는지 여부를 반환

UserDetailsService와 UserDetails의 동작 순서

사용자 로그인 시도 > 인증 요청 > 사용자 정보 조회 >

UserDetails 객체 생성 > UserDetails 반환 > 이증 처리>

권한 확인 > 인증 결과 처리

  1. 사용자가 로그인 폼에 사용자 이름(username)과 비밀번호(password)를 입력한다. - 사용자 로그인 시도
  2. Spring Security가 입력한 사용자 이름을 사용하여 UserDetailsService의 loadUserByUsername(String username) 메서드를 호출한다. - 인증 요청
  3. UserDetailsService의 구현체에서 loadUserByUsername 메서드가 호출되면 데이터 베이스에서 해당 사용자 이름을 가진 사용자 정보를 조회한다. - 사용자 정보 조회
  4. 조회한 사용자 정보를 바탕으로 UserDetails 객체를 생성한다. 이 객체에는 사용자의 비밀번호, 권한, 계정 활성화 여부 등의 정보를 포함하고 있다. 그리고 일반적으로 User 클래스의 인스턴스이다. - UserDetails 객체 생성 
  5. 생성된 UserDetails 객체가 loadUserByUsername 메서드의 반환값으로 돌아온다. - UserDetails 반환
  6. Spring Security는 반환된 UserDetails 객체를 사용하여 입력된 비밀번호와 UserDetails의 비밀번호를 비교한다. 비교 결과에 따라 인증 성공 여부가 결정된다. - 인증 처리
  7. 인증이 성공하면 UserDetails의 getAuthorities() 메서드를 호출하여 사용자의 권한 목록을 가져온다. 권한 정보는 사용자가 요청한 자원에 접근할 수 있는지 여부를 확인하는 데 사용된다. - 권한 확인
  8. 인증이 성공하면 사용자는 시스템 로그인되고, 권한에 따라 접근할 수 있는 자원이 결정된다. 인증이 실패하면, 로그인 오류 메시지가 사용자에게 표시된다. - 인증 결과 처리

요약

요약하자면 UserDetailsService의 loadUserByUsername(String username) 메서드는 입력된 username의 사용자를 데이터베이스에서 찾아온 후, 그 사용자 정보를 기반으로 UserDetails 객체를 생성하여 반환한다. UserDetails 객체 안에는 getUsername(), getPassword(), getAuthorites() 등 여러 메서드가 정의되어 있다.


GrantedAuthority

  • Spring Security에서 사용자의 권한(authorization)을 표현하기 위한 인터페이스이다.
  • 주로 사용자의 권한을 관리하고, 접근 제어를 수행하는데 사용된다.
  • 권한 표현
    • GrantedAuthority는 사용자가 가진 권한을 나타내는 객체이다.
    • 예를들어 "ROLE_ADMIN", "ROLE_USER"와 같은 권한을 표현할 수 있다.
  • 인터페이스
    • GrantedAuthority는 인터페이스이다. 이 인터페이스의 구체적인 구현체는 SimpleGrantedAuthority이다.

SimpleGrantedAuthority(...)

  • Spring Security에서 사용되는 클래스로, 사용자의 권한을 표현하는 객체를 생성하는 역할을 한다. 
  • GrantedAuthority 인터페이스를 구현하고 있으며, 사용자의 권한 정보를 담고 있다.
  • SimpleGrantedAuthority 클래스는 GrantedAuthority 인터페이스를 구현하여 권한의 이름을 저장하고 제공한다.
  • SimpleGrantedAuthority는 권한을 표현하는 표준 구현체이지만, 커스터마이징이 가능하다. 하지만 일반적으로 SimpleGrantedAuthority로 사용하며 코드의 가독성과 유지 보수성을 위해 많은 개발자들이 기본 구현체를 사용하는 경향이 있다.
  • 쉽게 설명하자면 GrantedAuthority 인터페이스의 메서드를 사용하기 위해서는 구현체가 필요한데 그 구현체가 SimpleGratedAuthority이다. 그래서 SimpleGratedAuthority는 GrantedAuthority의 메서드를 사용할 수 있다.

.stream()

  • Java의 Stream API의 일부로, 컬렉션(예: 리스트, 배열 등)에 대해 다양한 연산을 수행할 수 있도록 도와주는 기능이다.
  • 컬렉션을 스트림으로 변환하여, 그 스트림을 통해 복잡한 데이터 처리를 간결하고 직관적으로 처리를 할 수 있게 해준다.
  • 컬렉션 변환
    • user.getRoles()가 반환하는 역할 목록을 스트림으로 변환한다. 이렇게 하면 목록의 각 요소에 대해 연산을 수행할 수 있다.
  • 지연 연산
    • 스트림은 데이터를 "지연(lazy)" 방식으로 처리한다. 즉, 실제로 연산이 필요할 때까지 계산을 미룬다. 이렇게 하면 메모리 사용을 최적화할 수 있다.
  • 연산 체인
    • 스트림 API를 사용하면 여러 연산을 연결(chain)할 수 있다. 예를들어, map(), filter(), reduce()와 같은 메서드를 사용하여 데이터를 변환하거나 필터링할 수 있다.

예시

// 예시
List<GrantedAuthority> authorities = user.getRoles().stream()
    .map(role -> new SimpleGrantedAuthority(role.getName()))
    .collect(Collectors.toList());
  • user.getRoles().stream(): user 객체의 역할 목록을 스트림으로 변환합니다.
  • map(role -> new SimpleGrantedAuthority(role.getName())): 각 역할을 SimpleGrantedAuthority 객체로 변환합니다. 이 부분이 실제로 역할 목록의 각 요소를 변환하는 연산입니다.
  • collect(Collectors.toList()): 변환된 요소들을 다시 리스트 형태로 수집하여 List<GrantedAuthority> 타입의 authorities 리스트를 만듭니다.

요약

  • UserDetailsService : 사용자 정보를 가져오는데 사용되는 인터페이스. 사용자 정보를 제공.
  • UserDetails : 사용자의 정보를 담고 있는 인터페이스. 인증, 인가를 위해 필요한 정보를 제공.
  • GrantedAuthority: 사용자의 권한을 표현하기 위한 인터페이스. ROLE_ADMIN, ROLE_USER 같은 권한.
  • SimpleGtrantedAuthority: 사용자의 권한을 표현하는 객체를 생성. GrantedAuthority 인터페이스의 구현체.