[spring]스프링

[Spring 게시판] 13. UserDetails, UserDetailsService를 이용한 User 폴더 구조

낭만적인 부자 2023. 9. 3. 03:02

User 정보를 관리하는 코드를 작성해 보겠습니다.

다른 Entity들과는 다르게 User 클래스는 UserDetails를 상속받습니다.

또한 UserService 클래스는 UserDetailsService를 상속받습니다.

 

UserDetails와 UserDetailsService는

spring security 의존성을 추가함으로써 이용 가능합니다.

 


build.gradle

spring-boot-starter-security를 추가해줍니다.

 

 


User.java

 

package com.homepage.user.entity;

import java.util.Collection;
import java.util.List;

import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.homepage.user.dto.Role;

import jakarta.persistence.Entity;
import jakarta.persistence.EnumType;
import jakarta.persistence.Enumerated;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.Table;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@Builder
@AllArgsConstructor
@NoArgsConstructor
@Entity
@Table(name="user")
public class User implements UserDetails{
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	private Integer id;
	//로그인 시 사용할 id를 uid라고 표현
	private String uid;
	private String pwd;
	private String nick;
	private String email;
	@Enumerated(EnumType.STRING)
	private Role role;
	
	@Override
	public Collection<? extends GrantedAuthority> getAuthorities() {
		return List.of(new SimpleGrantedAuthority(role.name()));
	}

	@Override
	public boolean isAccountNonExpired() {
		return true;
	}
	
	@Override
	public boolean isAccountNonLocked() {
		return true;
	}
	
	@Override
	public boolean isCredentialsNonExpired() {
		return true;
	}
	
	@Override
	public String getPassword() {
		return pwd;
	}

	@Override
	public String getUsername() {
		return nick;
	}

	@Override
	public boolean isEnabled() {
		return true;
	}
}

 

 

UserDetails는 spring security의 사용자 정보를 제공합니다.

위의 User클래스에서는 7개의 메서드를 오버라이딩 했습니다.

각각의 메서드가 무엇을 의미하는지 간단하게 적어보겠습니다.

 

UserDetails

getAuthorities() GrantedAuthority의 목록을 반환합니다. User가 가지고 있는 권한들을 담고 있습니다.
isAccountNonExpired() 계정이 만료되었는지 나타냅니다. 비밀번호 만료나 임시 계정, 계정 활성화 관리에 사용됩니다. 결과값이 false라면 계정이 만료된 것입니다.
isAccountNonLocked() 계정이 잠겼는지 나타냅니다. 잠겼다면 인증을 거부합니다.
isCredentialsNonExpired() 비밀번호가 만료되었는지 나타냅니다.
getPassword() User의 고유 식별자를 반환합니다. 고유 식별자로는 주로 ID를 이용합니다.
getUsername() User의 고유 식별자를 반환합니다. 고유 식별자로는 주로 ID를 이용합니다.
isEnabled() 사용자 계정이 활성화 되었는지 확인합니다.
isAccountNonExpired()와 차이점은 isAccountNonExpired()는 예정된 시간이 지나 자동으로 권한이 만료되었음을 나타낸다는 것입니다.

 

 


Role.java

 

package com.homepage.user.dto;

public enum Role {
	USER,
	ADMIN
}

 

 


UserRepository.java

 

package com.homepage.user.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.homepage.user.entity.User;

public interface UserRepository extends JpaRepository<User, Integer>{

}

 

 


UserService.java

 

import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import com.homepage.user.entity.User;
import com.homepage.user.repository.UserRepository;

import lombok.RequiredArgsConstructor;

@Service
@RequiredArgsConstructor
public class UserService implements UserDetailsService{
	private final UserRepository userRepository;
	
	@Override
	public User loadUserByUsername(String id) throws UsernameNotFoundException{
		User user=userRepository.findById(Integer.parseInt(id)).orElseThrow();
		if(user==null) {
			throw new UsernameNotFoundException(id);
		}
		return user;
	}
	
}

 

UserDetailsService를 상속받았습니다.

loadUserByUsername을 오버라이딩 해야합니다.

loadUserByUsername는 사용자의 식별값을 이용해 User 데이터를 반환하는 코드입니다.

식별값은 email이나 uid값과 같은, 로그인 시 이용할 값으로 설정하기 때문에 String으로 입력합니다.