Spring Security - UserDetails , UserDetailsService
UserDetails 란?
Spring Security에서 사용자의 정보를 담는 인터페이스이다.
Spring Security에서 사용자의 정보를 불러오기 위해서 구현해야 하는 인터페이스로 기본 오버라이드 메서드들은 아래와 같다.
| 메소드 | 리턴 타입 | 설명 | 기본값 | 
| getAuthorities() | Collection<? extends GrantedAuthority> | 계정의 권한 목록을 리턴 | |
| getPassword() | String | 계정의 비밀번호를 리턴 | |
| getUsername() | String | 계정의 고유한 값을 리턴 ( ex : DB PK값, 중복이 없는 이메일 값 ) | |
| isAccountNonExpired() | boolean | 계정의 만료 여부 리턴 | true ( 만료 안됨 ) | 
| isAccountNonLocked() | boolean | 계정의 잠김 여부 리턴 | true ( 잠기지 않음 ) | 
| isCredentialsNonExpired() | boolean | 비밀번호 만료 여부 리턴 | true ( 만료 안됨 ) | 
| isEnabled() | boolean | 계정의 활성화 여부 리턴 | true ( 활성화 됨 ) | 
여기서 잘 봐야하는 메서드가 getUsername()이다.
username은 계정의 고유한 값인데 다른 블로그들을 보니까 다들 email( 로그인용 아이디 )을 넘겨준다고 하지만 email( 로그인용 아이디 )은 SSO 같은 서버를 만들게 되면 정책에 따라서 중복이 될 수도 있기에 나와 같은 경우는 보통 DB에서 User Table에 PK 값을 넘겨준다.
CustomUserDetails 구현하기
대부분의 경우 Spring Security의 기본 UserDetails로는 실무에서 필요한 정보를 모두 담을 수 없기에 아래와 같은 CustomUserDetails를 구현하여 사용한다.
@Getter
public class CustomUserDetails implements UserDetails, Serializable {
    private static final long serialVersionUID = 174726374856727L;
    private String id;	// DB에서 PK 값
    private String loginId;		// 로그인용 ID 값
    private String password;	// 비밀번호
    private String email;	//이메일
    private boolean emailVerified;	//이메일 인증 여부
    private boolean locked;	//계정 잠김 여부
    private String nickname;	//닉네임
    private Collection<GrantedAuthority> authorities;	//권한 목록
	
    
    /**
    * 해당 유저의 권한 목록
    */
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
           return authorities;
    }
	/**
    * 비밀번호
    */
	@Override
    public String getPassword() {
        return password;
    }
	/**
    * PK값
    */
    @Override
    public String getUsername() {
        return id;
    }
    /**
     * 계정 만료 여부
     * true : 만료 안됨
     * false : 만료
     * @return
     */
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }
    /**
     * 계정 잠김 여부
     * true : 잠기지 않음
     * false : 잠김
     * @return
     */
    @Override
    public boolean isAccountNonLocked() {
        return locked;
    }
    /**
     * 비밀번호 만료 여부
     * true : 만료 안됨
     * false : 만료
     * @return
     */
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }
    /**
     * 사용자 활성화 여부
     * ture : 활성화
     * false : 비활성화
     * @return
     */
    @Override
    public boolean isEnabled() {
        //이메일이 인증되어 있고 계정이 잠겨있지 않으면 true
        return (emailVerified && !locked);
    }
}
UserDetailsService 란?
Spring Security에서 유저의 정보를 가져오는 인터페이스이다.
Spring Security에서 유저의 정보를 불러오기 위해서 구현해야하는 인터페이스로 기본 오버라이드 메서드는 아래와 같다.
| 메소드 | 리턴 타입 | 설명 | 
| loadUserByUsername | UserDetails | 유저의 정보를 불러와서 UserDetails로 리턴 | 
UserDetailsServiceImpl 구현하기
@Service
@RequiredArgsConstructor
public class UserDetailsServiceImpl implements UserDetailsService {
    private final UserInfoRepository userInfoRepository;
    @Override
    public UserDetails loadUserByUsername(String loginId) throws UsernameNotFoundException {
        UserInfo userInfo = userInfoRepository.findByLoginId(loginId).orElseThrow(() -> new UsernameNotFoundException("not found loginId : " + loginId));
        CustomUserDetails customUserDetails = new CustomUserDetails();
        // 값 세팅 로직 시작
        ...
        // 값 세팅 로직 끝
        return customUserDetails;
    }
}
아마 대부분의 프로젝트에서 로그인 화면에서는 아래와 같은 HTML로 login용 ID와 Password를 함께 넘길 것이다.
<form action="/login" method="post">
  <input type="text" id="loginId" name="loginId" autofocus="autofocus" /> <br />
  <input type="password" id="password" name="password" /> <br />
  <input type="submit" value="Log in" />
</form>아래에 있는 시큐리티 설정을 해준다면
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.formLogin()
                .usernameParameter("loginId")
                .passwordParameter("password")
	}
    
}Spring Security에서 loginId를 넘겨줄 것이고 loadUserByUsername 에서 해당 값으로 DB를 조회 후 저장되어 있는 유저 정보를 가져온다.
그 후에 원하는 형태로 CustomUserDetails를 세팅해준 후 리턴해주면 Spring Security에서는 해당 유저의 정보를 조회할 때에는 CustomUserDetails에 세팅된 값으로 조회를 한 후 로직을 처리해준다.
SecurityContextHolder에서 UserDetails 불러오기
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
UserDetails userDetails = (UserDetails)principal;
String username = userDetails.getUsername();
String password = userDetails.getPassword();
기본적으로 Spring Security의 principal 객체는 Object 형태로 UserDetails를 형변환 해야 한다.
'Spring > spring security' 카테고리의 다른 글
| Spring Security - LogoutFilter 란 (0) | 2021.09.10 | 
|---|---|
| Spring Security - UsernamePasswordAuthenticationFilter 란 (1) | 2021.09.09 | 
| spring security DB를 이용한 로그인 구현 3 ( 로그아웃 하기 ) - 삽질중인 개발자 (0) | 2020.03.29 | 
| 스프링 시큐리티 DB를 이용한 로그인 구현 2 ( ajax 로그인 ) - 삽질중인 개발자 (3) | 2020.03.28 | 
| 스프링 시큐리티 DB를 이용한 로그인 구현 1 ( 회원 설정 및 일반 로그인 ) - 삽질중인 개발자 (2) | 2020.02.16 | 
 
 
									
								