반응형

UserDetails

UserDetails interface는 스프링 시큐리티가 사용자의 인증 및 권한 부여를 위해 필요한 정보를제공하기 위한 인터페이스

결국 사용자 정보를 효과적으로 이해하고 이를 기반으로 보안 구현

기본적인 메소드를 스프링 시큐리티에서 제공 거기에다가 조금 Custom 해서 내 마음대로 바꿔서 사용

뼈대에 살붙이기 -> 편리하다 

 

저장 위치

SecurityContextHolder -> Context -> Authentication -> Principal  -> UserDetails 객체가 저장되어있다

 

아래와 같이 UserDetails를 구현하는 PrincipalDetails class 를 생성해서 사용한다.

주의!! 모든 오버라이드 메소드는 자신이 변경해서 사용이 가능하다 

 

getAuthorities() 부분에서 ROLE_ADMIN ,ROLE_USER 형식으로 반환해 주어야한다

// Security Session => Authentication => UserDetails(PrincipalDetails)
@RequiredArgsConstructor
public class PrincipalDetails implements UserDetails {

    private final User user;

    //해당 User의 권한을 리턴하는 곳
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collect = new ArrayList<>();
        collect.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return user.getRole();
            }
        });
        return collect;
    }
    //비밀번호
    @Override
    public String getPassword() {
        return user.getPassword();
    }
    //User의 이메일도 되지만 PK값을 넘기면 중복을 없앨수 있다
    @Override
    public Long getUsername() {
//        return user.getUsername();
        return user.getId();
    }

    //계정 만료 여부
    //true : 만료 안됨
    //false : 만료
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    //계정 잠김 여부
    //true : 잠기지않음
    //false : 잠김
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    //비밀번호 만료 여부
    //true : 만료 안됨
    //false : 만료
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    //1년동안 회원이 로그인을 안하면 휴먼 계정으로 변경
    //true : 활성화
    //false : 비활성화
    @Override
    public boolean isEnabled() {
        //User Entity에 Timestamp loginDate 만들고
        //현재시간 - 로그인시간 => 1년 초과하면 return false; 하는 과정으로
        //휴면 계정을 판단할 수 있다.
        return true;
    }
}

 

 

 

UserDetailsService 

동작 방법

사용자가 로그인을 할때 스프링 시큐리티에서는 loadUserByUsername 메소드를 호출하게 된다.

따라서 우리는 loadUserByUsername 메서드를 가지고 있는 UserDetailsService 인터페이스를 구현하는 새로운 클래스를 만들어서 

자신만의 loadUserByUsername의 기능을 구현해주어야 한다.

 

Spring Security의 인증 프로세스는 UserDtailsService를 사용해서 사용자를 검새후 UserDetails객체를 생성한다

위에서 보다시피 UserDetails 객체 : 사용자의 인증 및 권한 부여에 필요한 정보를 담고있다.

유저 정보 -> UserDetailsService(loadUserByUsername) -> UserDetails 객체 생성

 

UserDetailsService를 구현하면 loadUserByUsername 메서드를 제공할 수 있는데 이 메서드는 사용자 이름을 받아

해당 사용자의 정보를 검색한다.

 

비밀번호 검증은 시큐리티가 UsernameAndPasswordToken로 내부에서 알아서 검증해준다

구현한 모습

//시큐리티 session = Authentication = UserDetails
//principalDetails -> UserDetails type
//시큐리티 설정에서 loginProcessingUrl("login");
//login 요청이 오면 자동으로 UserDetailsService타입으로 IoC 되어 있는 loadUserByUsername함수가 실행

@Service
@RequiredArgsConstructor
public class PrincipalDetailsService implements UserDetailsService {

    private final UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        //알다시피 findBy규칙 Username 문법
        // select * from user where username = ? 쿼리가 실행된다. -> jpa 에서 알아서 메소드 이름 기준으로 생성해줌
        User userEntity = userRepository.findByUsername(username);
        // 이 부분에서 유저 정보에 대한 값 세팅 로직을 작성
        if (userEntity != null){
            return new PrincipalDetails(userEntity);
        }
        return null;
    }
}

 

반응형

+ Recent posts