본문 바로가기

SPRING SECURITY

[SPRING SECURITY] 실제 DB에서 인증하기

DB로부터 사용자를 직접 조회하고, 조회한 사용자를 통해서 인증처리를 이루어질 수 있도록 구현하려고 한다. 그러기 위해 UserServiceDetailsService를 커스터마이징을 한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
@Service("userDetailService")
public class CustomUserDetailsService implements UserDetailsService {
 
    @Autowired
    private UserRepository userRepository;
 
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        Account account = userRepository.findByUsername(username);
 
        if (account == null){
            throw new UsernameNotFoundException("UsernameNotFoundException");
        }
 
        List<GrantedAuthority> roles = new ArrayList<>();
        roles.add(new SimpleGrantedAuthority(account.getRole()));
 
        AccountContext accountContext = new AccountContext(account, roles);
 
        return accountContext;
    }
}
cs

2 - @Service을 통해 빈으로 등록한다.

3 - UserDetailsService 인터페이스를 상속하면 loadUserByUsername을 구현해야 하는데 이 메서드의 반환 타입은 UserDetails이다.

10~14 - Repository에서 username을 통해 account객체를 찾아 반환하도록 하였고 null이면 예외 처리가 되도록 한다.

16 - UserDetails로 반환하려면 account객체와 role이 필요하기 때문에 GrantedAuthrotiy타입으로 반환하는 리스트를 만들어 role을 추가한 뒤 AccountContext에 username으로 찾은 account와 role을 파라미터로 하여 생성자에 넘겨주었다.

 

AccountContext >>

loadUserByUsername메서드는 UserDetails객체를 타입으로 반환해야하기 때문에 Spring Security가 제공하는 UserDetails의 구현체인 User를 상속으로 하는 새로운 클래스를 만들어서 값을 넘기고 반환시켜준다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;
    }
}
 
cs