[ODOP] 95일차 - DB 연동 인증 : CustomUserDetailsService

[ODOP] 95일차 - DB 연동 인증 : CustomUserDetailsService
그동안 인증을 위한 사용자는 메모리 형태로 올려서 인증 했다.
하지만 이제 DB 에서 처리 해보자

DB 에서 사용자를 가져오고, 인증을 하기 위해서는 다음 두개의 클래스를 구현해야 한다.

  1. UserDetailsService : interface
  2. UserDetails : interface

둘 다 인터페이스 이지만, UserDetails 인터페이스는 스프링에서 기본 구현체를 제공하기 때문에 해당 구현체를 오버라이딩 하여 사용하면 된다.

구현

package com.pollra.security.application.config.security.service;

import com.pollra.security.application.config.security.entity.Account;
import com.pollra.security.application.config.security.repository.UserRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.security.core.GrantedAuthority;
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 java.util.ArrayList;
import java.util.Collection;
import java.util.Objects;

@Service
@RequiredArgsConstructor
public class CustomUserDetailsService implements UserDetailsService {

    private final UserRepository userRepository;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Account account = userRepository.findByUsername(username);

        if(Objects.isNull(account)) {
            throw new RuntimeException("계정을 찾을 수 없습니다.");
        }

        Collection<GrantedAuthority> roles = new ArrayList<>();
        roles.add(new SimpleGrantedAuthority(account.getRole()));

        AccountContext accountContext = new AccountContext(account, roles);

        return accountContext;
    }
}
package com.pollra.security.application.config.security.service;

import com.pollra.security.application.config.security.entity.Account;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;

import java.util.Collection;

public class AccountContext extends User {

    private final Account account;

    public AccountContext(Account account, Collection<? extends GrantedAuthority> authorities) {
        super(account.getUsername(), account.getPassword(), authorities);
        this.account = account;
    }

    public Account getAccount() {
        return account;
    }
}

여기서 눈에 띄는 것은 AccountContext 에서 상속 받고 있는 User 라는 클래스 이다.

이 친구는 위에서 말했던 Spring security 에서 제공해주는 UserDetails 인터페이스의 기본 구현체

생성자를 잘 보면 super 생성자를 호출하고 있는데, 필수적으로 포함되어야 하는 중요한 요소 이다.