[Spring Security] 커스텀 로그인 검증 로직

원모어깨찰빵·2024년 3월 12일
0

스프링

목록 보기
9/17
post-thumbnail

구조도


본 연습용 프로젝트는 JWT를 사용하지 않았고, 최대한 간단한 로직만을 사용하였습니다.

유저 네임(아이디)의 유니크 설정

@Column(unique = true)
    private String username; //아이디

엔티티에서 유저 아이디에 unique설정을 해준다.

중복 가입 방지 로직

먼저, repository에 existsBy문으로 해당 아이디가 존재하는지 확인하는 메소드를 추가한다.

public interface UserRepository extends JpaRepository<UserEntity, Long> {
    boolean existsByUsername(String username);
}

이후 해당 메소드를 사용하여 서비스단에서 중복 가입 방지 로직을 추가한다.

public void joinProcess(JoinDto joinDto){
        //db에 동일한 username이 존재하는지 검증
        boolean isUser=userRepository.existsByUsername(joinDto.getUsername());
        if(isUser) return;  //존재시 return(exception발생시켜야함)
        //이후 회원저장로직
        UserEntity user=new UserEntity();
        user.setUsername(joinDto.getUsername());
        user.setPassword(bCryptPasswordEncoder.encode(joinDto.getPassword())); //비밀번호 암호화 후 저장
        user.setRole("ROLE_USER"); //유저의 권한 지정
        userRepository.save(user);
    }

UserDetailsService 구현

Spring Security에서 유저의 정보를 가져오는 인터페이스이다.
loadUserByUsername 메소드를 오버라이딩 해주어야 한다.

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private UserRepository userRepository;
    @Override  //로그인시 security config가 검증을 위하여 username을 넣어서 보낸다.
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        UserEntity user=userRepository.findByUsername(username);
        if(user!=null){
            return new CustomUserDetails(user);
        }
        return null;
    }
}

UserDetails 구현

Spring Security에서 사용자의 정보를 담는 인터페이스로, 사용자의 정보를 구현하기 위하여 구현해야 한다.
etAuthorities() Collection<? extends GrantedAuthority>
getPassword()
getUsername()
isAccountNonExpired()
isAccountNonLocked()
isCredentialsNonExpired()
isEnabled()
메소드들을 오버라이딩해야 한다.

public class CustomUserDetails implements UserDetails {
    private UserEntity user;
    public CustomUserDetails(UserEntity user){
        this.user=user;
    }
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {  //사용자의 권한 리턴(role값)
        Collection<GrantedAuthority> collection=new ArrayList<>();
        collection.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return user.getRole();
            }
        });
        return collection;
    }
    @Override
    public String getPassword() {
        return user.getPassword();
    }
    @Override
    public String getUsername() { //여기서 username은 PK로 지정하여야 한다.(중복이 아예 불가능한 필드인)
        return user.getUsername();
    }
    @Override
    public boolean isAccountNonExpired() { //사용자 계정이 만료되었는지 - true : 만료 안됨
        return true;
    }
    @Override
    public boolean isAccountNonLocked() {  //사용자가 잠겨있는지 - true : 안잠김
        return true;
    }
    @Override
    public boolean isCredentialsNonExpired() { //자격(비밀번호) 증명 만료 여부 -true: 만료안됨
        return true;
    }
    @Override
    public boolean isEnabled() {  //사용자의 사용 가능 여부 : true : 사용가능
        return true;
    }
}

Security Config에서 사용자의 정보를 UserDetailsService를 통하여 불러올 때, 유저의 정보를 감싸고 있는 DTO의 역할을 하는 것이 UserDetails이다.

Reference

개발자 유미 유튜브
개발자 유미 노션
삽질중인 개발자 블로그

profile
https://fuzzy-hose-356.notion.site/1ee34212ee2d42bdbb3c4a258a672612

0개의 댓글