AuthenticationManager는 UsernamePasswordAuthenticationFilter 에게 호출되어 인증을 AuthenticationProvider 에게 위임한다.
이때 AuthenticationProvider 가 사용하는 객체는 UserDetailsService, UserDetails 객체이다.
각각 유저의 세부정보를 가져오는 역할과 유저정보를 가지고 있는 역할을 한다.
DB를 연동하여 이를 사용하려면 UserDetailsService와 UserDetails의 구현은 불가피한 듯 하다.
일단 흐름대로 가보면 UserDetailsService > UserDetails > AuthenticationProvider 순.
UserDetailsService 의 구현부터 들어간다. 보면, Bean identifier 로 userDetailsService를 주었다.
DB 에서 유저정보를 받아내 비교할 것으므로 UserDetailsService 의 loadByUsername 메서드는 DB에서 끌어와야한다.
여기서 정보가 없다면 동작 Flow에 맞게 UsernameNotFoundException 을 던진다.
정보가 있다면 동작 Flow에 맞게 UserDetails 타입의 객체를 리턴시켜주면 된다.
즉, UserDetails 타입의 객체가 필요하다는 이야기이다.
import com.example.securityapp.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
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.List;
@Service("userDetailsService")
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())); // GrantedAuthority 는 인터페이스, GrantedAuthority 의 구현객체 중 하나인 SimpleGrantedAuthority 사용.
//UserDetailsService 작동 과정에서 UserDetails 타입으로 리턴해주어야한다.
AccountContext accountContext = new AccountContext(account, roles);
return accountContext;
}
}
User 클래스는 SpringSecurity 에 정의된 클래스로서 UserDetails 를 구현하고 있다.
- 부모 생성자를 호출하여 Entity 객체를 집어넣는다. username, password, Collection<GrantedAuthority> 의 생성자지만 상황에 맞게 Entity 인 Account 객체를 넣었다.
- Account 타입의 멤버변수를 선언하여, 나중에 사용하기 위해 Getter 를 정의했다.
** 가만히 보면 생성자의 3번째 파라미터는 Collection<GrantedAuthority> 이다. 이에 맞게 위의 UserDetailsService 구현객체의 loadByUsername 메서드 재정의 블록에서 List<GrantedAuthortity> roles 를 정의 후 구현 객체인 SimpleGrantedAuthority 클래스에 Account의 권한정보를 담아 생성한 후 roles 에 저장했다.
import com.example.securityapp.domain.Account;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.User;
import java.util.Collection;
public class AccountContext extends User {// UserDetail 를 구현한 User 클래스를 상속
private final Account account;
//생성자 재정의
public AccountContext(Account account, Collection<? extends GrantedAuthority> authorities) {
super(account.getUsername(),
account.getPassword(), authorities);
this.account = account; // 나중에 account 를 참조하기 위해 멤버변수로 선언
}
public Account getAccount() {
return account;
}
}
엄연히 "인증" 과정이므로 전에 보았던 회원 가입과는 다르다.
UserDetailsService : DB 에서 유저정보를 찾아 UserDetails 타입으로 넘겨야함
UserDetails : 인증과정에서 UserDetailsService 에서 리턴 됨, DB 에서 가져온 VO객체를 생성자로 받아 username , password에 저장해야 함.
의 경로 순서로 볼 수 있다.
등록은 Security 설정클래스 : configure(AuthenticationManagerBuilder builder)
Authentication Flow 를 고려할 때에 AuthenticationManger가 AuthenticationProvider 에게 인증을 위임한다고 했다.
즉 인증과정 에서 사용될 UserDetailsService 는 AuthenticationManager에 등록해야한다.
AuthenticationManagerBuilder 의 userDetailsService(userDetailsService) 메서드로 등록가능하다.
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {// 인증시 구현한 UserDetailsService 객체를 등록하려면 해당 메서드 재정의
auth.userDetailsService(userDetailsService);//등록
}
'springframework > 시작하자SpringSecurity' 카테고리의 다른 글
28.CustonLoginPage (0) | 2020.09.28 |
---|---|
27.인증구현, CustomAuthenticationProvider (0) | 2020.09.27 |
26.PasswordEncoder (0) | 2020.09.27 |
25.정적 자원 관리 - WebIgnore 설정 (0) | 2020.09.27 |
24.SpringSecurity 필터, 아키텍쳐 정리 (0) | 2020.09.23 |