- getAuthorities() : 사용자가 가지는 권한에 대한 정보
- getPassword() : 인증을 마무리하기 위한 패스워드 정보
- getUsername() : 인증에 필요한 아이디와 같은 정보
- 계정 만료 여부 : 더이상 사용이 불가능한 계정인지 알 수 있는 정보
- 계정 잠김 여부 : 현재 계정의 잠김 여부
@Log4j2
//User 클래스는 UserDetailsService로부터 핵심 유저 정보를 모델링한다.
//User 클래스를 상속하고 부모 클래스인 User 클래스의 생성자를 호출할 수 있는 코드를 만든다.
//부모 클래스인 User 클래스에 사용자 정의 생성자가 있으므로 반드시 호출할 필요가 있다.
//ClubAuthMemberDTO는 DTO 역할을 수행하는 클래스인 동시에 스프링 시큐리티에서 인가/인증 작업에 사용할 수 있다.
//password는 부모 클래스를 사용하므로 별도의 멤버 변수로 선언하지 않는다.
public class ClubAuthMemberDTO extends User {
private String email;
private String name;
private boolean fromSocial;
public ClubAuthMemberDTO(String username, String password, boolean fromSocial, Collection<? extends GrantedAuthority> authorities){
//User 클래스의 생성자를 호출한다.
super(username, password, authorities);
this.email=username;
this.fromSocial=fromSocial;
}
}
ClubMember가 ClubAuthMemberDTO라는 타입으로 처리된 가장 큰 이유는 사용자의 정보를 가져오는 핵심적인 역할을 하는 UserDetailsService라는 인터페이스 때문입니다.
스프링 시큐리티의 구조에서 인증을 담당하는 AuthenticationManager는 내부적으로 UserDetailsService를 호출해서 사용자의 정보를 가져온다.
현재 예제와 같이 JPA로 사용자의 정보를 가져오고 싶다면 이 부분을 UserDetailsService가 이용하는 구조로 작성할 필요가 있습니다.
추가된 service패키지에는 이를 위한 ClubUserDetailsService 클래스를 다음과 같이 추가합니다.
mport lombok.extern.log4j.Log4j2;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
@Log4j2
//Service어노테이션을 사용해서 자동으로 스프링에서 빈으로 처리될 수 있게 한다.
//ClubUserDetailsService가 빈(Bean)으로 등록되면 이를 자동으로 스프링 시큐리티에서
//UserDetailsService로 인식하기 때문에 기존에 임시로 코드로 직접 설정한
//configure(AuthenticationManagerBuilder auth) 부분을 사용하지 않도록 수정한다.
@Service
public class ClubUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("ClubUserDetailsService loadUserByUsername"+username);
return null;
}
}
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.young.club.entity.ClubMember;
import org.young.club.repository.ClubMemberRepository;
import org.young.club.security.dto.ClubAuthMemberDTO;
import java.util.Optional;
import java.util.stream.Collectors;
@Log4j2
//Service어노테이션을 사용해서 자동으로 스프링에서 빈으로 처리될 수 있게 한다.
//ClubUserDetailsService가 빈(Bean)으로 등록되면 이를 자동으로 스프링 시큐리티에서
//UserDetailsService로 인식하기 때문에 기존에 임시로 코드로 직접 설정한
//configure(AuthenticationManagerBuilder auth) 부분을 사용하지 않도록 수정한다.
@Service
@RequiredArgsConstructor
public class ClubUserDetailsService implements UserDetailsService {
private final ClubMemberRepository clubMemberRepository;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
log.info("ClubUserDetailsService loadUserByUsername"+username);
Optional<ClubMember> result=clubMemberRepository.findByEmail(username, false);
System.out.println("username:"+username);
if(result.isPresent()==false){
throw new UsernameNotFoundException("Check Email or Social ");
}
ClubMember clubMember=result.get();
System.out.println(clubMember.getRoleSet().toString());
log.info("--------------------------");
log.info(clubMember);
//ClubMember를 UserDetails 타입으로 처리하기 위해서 ClubAuthMemberDTO 타입으로 변환
ClubAuthMemberDTO clubAuthMember=new ClubAuthMemberDTO(
clubMember.getEmail(),
clubMember.getPassword(),
clubMember.isFromSocial(),
//ClubMemberRole은 스프링 시큐리티에서 사용하는 SimpleGrantedAuthority로 변환,
//이때 'ROLE_'라는 접두어를 추가해서 사용한다.
//user95@zerock.org 같은 경우 롤이 3개다 [USER, MANAGER, ADMIN]
//이 각각을 [ROLE_ADMIN, ROLE_MANAGER, ROLE_USER]로 변환해서 Set으로 넣어주고 그 컬렉션을 반환한다.
clubMember.getRoleSet().stream()
.map(role->new SimpleGrantedAuthority("ROLE_"+role.name())).collect(Collectors.toSet()));
clubAuthMember.setName(clubMember.getName());
System.out.println(clubAuthMember.getAuthorities().toString());
return clubAuthMember;
}
}