Spring
[스프링] 시큐리티 -4 (SecurityContextHolder)
MbyM
2020. 10. 9. 19:05
- 참고 : 인프런 >>스프링 시큐리티 (백기선 강의)
SecurityContextHoder
- SecurityContext 제공 -> 기본적으로 ThreadLocal을 사용하여 SecurityContext를 제공
- ThreadLocal을 사용하여 어디에서나 접근 할 수 있다. (스레드가 달라지면 다른 전략을 고민)
- 최종적으로 "Authentification" 객체를 담고 있다.
* ThreadLocal(ThreadLocal<T>) ? 동일 스레드 내에서 공용으로 사용하는 저장소
- Java.lang 패키지에서 제공하는 쓰레드 범위 변수, 즉 쓰레드 수준의 데이터 저장소
- 각 스레드마다 독립적인 변수를 가지고 get(), set() 메소드를 통해 값에 대해 접근
- 한 스레드내에서 공용으로 사용하기 때문에, 파라미터로 데이터를 넘기지 않아도 접근 가능
- SecurityContextHolder의 기본전략
public class AccountContext {
private static final ThreadLocal<Account> ACCOUNT_THREAD_LOCAL
= new ThreadLocal<>();
public static void setAccount(Account account) {
ACCOUNT_THREAD_LOCAL.set(account);
}
public static Account getAccount() {
return ACCOUNT_THREAD_LOCAL.get();
}
}
//접근, 동일 스레드면 어디에서나 접근 가능
AccountContext.setAccount(new Account());
AccountContext.getAccount();
SecurityContext
- Authentification 제공 -> Principal + GrantAuthority
Principal ?
- 유저 정보
- UserDetailsService에서 Return한 그 객체 -> 유저 정보
- 객체는 UserDetails 타입
* UserDetails : 유저 정보와 스프링 시큐리티가 사용하는 Authentification 객체 사이의 어뎁터
* UserDetailsService : 유저 정보를 UserDetails 타입으로 가져오는 DAO (Data Acess Object) 인터페이스
예제
@Service
@RequiredArgsConstructor
public class AccountService implements UserDetailsService {
private final AccountRepository accountRepository;
private final PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
Account account = accountRepository.findByUsername(username);
if(account == null){
throw new UsernameNotFoundException(username);
}
return User.builder()
.username(account.getUsername())
.password(account.getPassword())
.roles(account.getRole())
.build();
}
public Account createNew(Account account) {
account.setPassword(passwordEncoder.encode(account.getPassword()));
return accountRepository.save(account);
}
}
GrantAuthority ?
- 권한
- "ROLE_USER", "ROLE_ADMIN" 등 Principal이 가지고 있는 "권한"
[Test -> Debug, SecurityContext]
Authentification