Spring

[스프링] 시큐리티 -4 (SecurityContextHolder)

MbyM 2020. 10. 9. 19:05

- 참고 : 인프런 >>스프링 시큐리티 (백기선 강의)

SecurityContextHolder

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