jnk1m
Foliage IT
jnk1m
전체 방문자
오늘
어제
  • 분류 전체보기 (209)
    • Today I Learned (34)
    • Java (47)
    • Database (15)
    • [NHN Academy] (27)
    • Spring (47)
    • HTML + CSS + JavaScript (11)
    • JSP (3)
    • Node.js (10)
    • React Native (2)
    • 기타 (8)
    • 스크랩 (5)

인기 글

최근 글

티스토리

hELLO · Designed By 정상우.
글쓰기 / 관리자
jnk1m

Foliage IT

[스프링 시큐리티] 사용자 관리 UserDetails, UserDetailsService, UserDetailsManager
Spring

[스프링 시큐리티] 사용자 관리 UserDetails, UserDetailsService, UserDetailsManager

2022. 12. 7. 20:18

사용자 관리


  • 스프링 시큐리티에서 사용자를 기술하는 UserDetails
  • 사용자가 실행할 수 있는 작업을 정의하는 GrantedAuthority 
  • UserDetailsService 계약을 확장하는 UserDetailsManager. 상속된 동작 외에 사용자 만들기. 사용자의 암호 수정이나 삭제 등의 작업도 지원한다. 

사용자 관리를 위해서는 UserDetailsService 및 UserDetailsManager 인터페이스를 이용한다.

 

 

UserDetailsService는 사용자 이름으로 사용자를 검색하는 역할만 한다. 이 작업은 프레임워크가 인증을 완료하는 데 반드시 필요한 유일한 작업이다. UserDetailsManager 는 대부분의 애플리케이션에 필요한 사웅자 추가, 수정, 삭제 작업을 추가한다. 

 

개발자는 스프링 시큐리티에 있는 UserDetails 계약을 구현해서 프레임워크가 이해할 수 있게 사용자를 기술해야 한다. 

스프링 시큐리티에서 사용자는 사용자가 수행할 수 있는 작업을 나타내는 이용 권리의 집합을 가진다. 

사용자가 수행할 수 있는 작업을 GrantedAuthority 인터페이스로 나타낸다.

👉 이를 종종 권한이라고 하며 사용자는 하나 이상의 권한을 가진다. 

 

사용자에게 허가된 작업을 권한(authority)라고 한다.

 

- UserDetailsService는 사용자 이름으로 찾은 사용자 세부 정보를 반환한다.

- UserDetails 계약은 사용자를 기술한다.

- 사용자는 GrantedAuthority 인터페이스로 나타내는 권한을 하나 이상 가진다.

- UserDetailsManager 계약은 UserDetailsService를 확장해서 암호 생성, 삭제, 변경 등의 작업을 추가한다.  

 


사용자 기술하기


프레임워크가 사용자를 인식할 수 있게 사용자를 나타내는 방법을 배우는 것은 인증 흐름을 구축하기 위한 필수 단계다. 애플리케이션은 사용자가 누구인지에 따라 특정 기능을 호출할 수 있는지 여부를 결정한다. 

 

스프링 시큐리티에서 사용자 정의는 UserDetails 계약을 준수해야 한다. UserDetails 계약은 스프링 시큐리티가 이해하는 방식으로 사용자를 나타낸다. 

public interface UserDetails extends Serializable {

    //앱 사용자가 수행할 수 있는 작업을 GrantedAuthority 인스턴스의 컬렉션으로 반환
   Collection<? extends GrantedAuthority> getAuthorities(); 
   
    
	//사용자 자격 증명을 반환
    String getPassword(); 
    
    String getUsername(); 
    
    
	//사용자 계정을 필요에 따라 활성화 또는 비활성화하는 네 메서드
    boolean isAccountNonExpired();

    boolean isAccountNonLocked();

    boolean isCredentialsNonExpired();

    boolean isEnabled();
}

 

getAuthorities() : 사용자에게 부여된 권한의 그룹을 반환하도록 구현한다. 

일반적으로 앱은 사용자가 애플리케이션에서 의미 있는 작업을 수행하도록 허용해야 한다. 예를 들어 사용자는 데이터를 읽고, 쓰고, 삭제할 수 있어야 한다. 사용자에게 작업을 수행할 이용 권리가 있거나 없다고 말하며 사용자가 가진 이용 권리를 나타내는 것이 권한이다. 

 

UserDetails 계약을 보면 다음과 같은 작업을 할 수 있다. 

  • 계정 만료
  • 계정 잠금
  • 자격 증명 만료
  • 계정 비활성화

👉 이러한 사용자 제한을 구현하려면 isAccountNonExpired(), isAccountNonLocked(), isCredentialsNonExpired(), isEnabled() 메서드를 재정의해서 true를 반환하게 해야한다. 
모든 애플리케이션에서 특정 조건에 계정이 만료되거나 잠기는 것은 아니다. 애플리케이션에서 이러한 기능을 구현할 필요가 없다면 단순하게 네 메서드가 true를 반환하게 하면 된다. 
(권한 부여가 실패하면 false, 그렇지 않으면 true)

 


GrantedAuthority 계약 살펴보기

권한은 사용자가 애플리케이션에서 수행할 수 있는 작업을 나타낸다. 
애플리케이션은 사용자가 필요로 하는 권한인 애플리케이션의 기능 요구 사항에 따라 다른 유형의 사용자를 구분해야 한다. 
스프링 시큐리티에서는 GrantedAuthority 인터페이스로 권한을 나타낸다.

 

GrantedAuthority 인터페이스는 사용자 세부 정보의 정의에 이용되며 사용자에게 허가된 이용 권리를 나타낸다. 
사용자는 권한이 하나도 없거나 여러 권한을 가질 수 있지만, 일반적으로 하나 이상의 권한을 가진다. 

public interface GrantedAuthority extends Serializable {
    String getAuthority();
}

이 인터페이스는 사용자 세부 정보의 정의에 이용되며 사용자에게 허가된 이용 권리를 나타낸다. 사용자는 권한이 하나도 없거나 여러 권한을 가질 수 있지만, 일반적으로 하나 이상의 권한을 가진다. 

 

권한을 만들려면 나중에 권한 부여 규칙을 작성할 때 참조할 수 있게 해당 이용 권리의 이름만 찾으면 된다. 

 


JPA Entity Mapping & UserDetails 인터페이스 구현 


@Entity
public class User{
	@Id
    private Long id;
    private String username;
    private String password;
    private String authority;
    
    //생략된 getter 와 setter
 }

User 클래스를 장식하는 SecurityUser라는 별도의 클래스를 만들어서 책임을 분리

SecurityUser 클래스는 UserDetails 계약을 구현하고 이를 이용해 사용자를 스프링 시큐리티 아키텍쳐에 연결한다. 

 

public class SecurityUser implements UserDetails{
	private final User user;
    
    public SecurityUser(User user){
    	this.user = user;
       }
     
    @Override
    public String getUsername(){
    	return user.getUsername();
    }
    
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities(){
    	return List.of(() -> user.getAuthority());
    }
    
    //생략된 코드
    
  }

 

스프링 시큐리티가 사용자를 관리하는 방법 지정

스프링 시큐리티는 사용자를 어떻게 관리할까? 자격 증명을 비교할 때는 어디에서 가져오고, 새 사용자를 추가하거나 기존 사용자를 변경할 때는 어떻게 해야 할까? UserDetailsService 클래스를 구현하는 다양한 방법을 실험해보자

 

 


 

UserDetailsService 계약의 이해


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

인증 구현은 loadUserByUsername(String name) 메서드를 호출해 주어진 사용자 이름을 가진 사용자의 세부 정보를 얻는다. 

‼️사용자 이름은 고유하다고 간주된다. 이 메서드가 반환하는 사용자는 UserDetails 계약의 구현이다. 

시스템이 어떻게 작동하는지와 관계없이 스프링 시큐리티에 필요한 것은 사용자 이름으로 사용자를 검색하는 구현을 제공하는 것이다. 

 

그럼 궁금한거.. loadUserByUsername은 인자로 collection 타입의 authorities를 받는데

resident도 authority 컬럼을 만들어서 권한을 넣어줘야 하는거 아닐까

 

UserDetailsService 계약 구현


수업 코드 참고 (securityApp)

loadUserByUsername의 리턴 타입이 UserDetails 인데 User를 리턴해도 되는 이유

User는 UserDetails의 구현체라서

 

책에 나온 예시


사용자 관리에 JdbcUserDetailsManager도 사용할 수 있다

 

 

정리

-UserDetails 인터페이스는 스프링 시큐리티에서 사용자를 기술하는 데 이용되는 계약이다.
-UserDetailsService 인터페이스는 애플리케이션이 사용자 세부 정보를 얻는 방법을 설명하기 위해 스프링 시큐리티의 인증 아키텍처에서 구현해야 하는 계약이다.
-UserDetai ISManager 인터페이스는 userDetailsService를 확장하고 사용자 생성, 변경, 삭제와 관련된 동작을 추가한다.
-스프링 시큐리티는 UserDetai Ls Manager 계약의 여러 구현을 제공한다. 이러한 구현에는 InMemoryuserDetai IsManager, JdbcUserDetailsManager, LdapUserDetailsManager가 있다.
-JdbcuserDetai lsManager는 JDBC를 직접 이용하므로 애플리케이션이 다른 프레임워크에 고정되지 않는다는 이점이 있다.

 

*도서 [스프링 시큐리티 인 액션] 을 읽고 정리한 내용입니다*

http://www.yes24.com/Product/Goods/112200347

 

스프링 시큐리티 인 액션 - YES24

모든 스프링 개발자에게 권장하는 스프링 시큐리티 필수 가이드!보안은 타협할 수 없는 중요한 요소다. 스프링 시큐리티로 안전하게 데이터를 전송하고 자격 증명을 검증하며 공격을 방지하는

www.yes24.com

 

    'Spring' 카테고리의 다른 글
    • Spring Boot에서 RestTemplate 빈 등록을 해야할까?
    • [에러] Interface 기반 DTO Projection NULL 에러 원인과 해결 방법
    • [스프링 시큐리티] 스프링 시큐리티의 흐름
    • NHN mart

    티스토리툴바