IT 서적/Spring Security In Action
ch05 : 인증 구현
SH.DevBlog
2024. 1. 2. 18:19
# AuthenticationProvider
- 인증 논리를 담당하는 영역(요청을 허용할지, 거부할지를 여기서 담당한다.)
- Spring Security에서 대표적으로 인증 논리를 정의하는 영역이다.
# Authentication 인터페이스
- 해당 인터페이스를 기준으로 구현하여 스프링 시큐리티 진영은 부가적인 기능들을 제공한다.
public interface Authentication extends Principal, Serializable {
Collection<? extends GrantedAuthority> getAuthorities() ;
Object getCredentials() ;
Object getDetails() ;
Object getPrincipal() ;
boolean isAuthenticated() ;
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException ;
}
- 현재 이 계약에서 알아야 할 메서드는 다음과 같다.
- isAuthenticated() - 인증 프로세스가 끝났으면 true를 반환하고 아직 진행 중이면 false를 반환한다.
- getCredentials() - 인증 프로세스에 이용된 암호나 비밀을 반환한다.
- getAuthorities() - 인증된 요청에 허가된 권한의 컬렉션을 반환한다.
# SecurityContext 이용
- Authentication 객체를 저장하는 인스턴스를 보안 컨텍스트라고 한다. (즉, 사용자의 정보를 저장한다.)
- 스프링 시큐리티는 보안 컨텍스트 관리 전략으로 세 가지 전략을 제공한다.
- MODE_THREADLOCAL : 각 스레드가 보안 컨텍스트에 독립적으로 저장
- MODE_INHERITABLETHREADLOCAL : MODE_THREADLOCAL과 비슷하지만 비동기 메서드의 경우 보안 컨텍스트를 다음 스레드로 복사하도록 시큐리티에 지시한다.
- MODE_GLOBAL : 모든 스레드가 같은 보안 컨텍스트 인스턴스를 보게 한다.
- 스프링 시큐리티는 보안 컨텍스트 관리 전략으로 세 가지 전략을 제공한다.
- 사용방법은 아래의 소스코드와 같다.
@GetMapping("/hello")
public String hello() {
SecurityContext context = SecurityContextHolder.getContext() ;
Authentication a = context.getAuthentication() ;
System.out.println(a.getName());
System.out.println(a.getCredentials());
System.out.println(a.getDetails());
System.out.println(a.getPrincipal());
a.getAuthorities().stream().forEach(value -> {
System.out.println(value.getAuthority());
});
return "Hello, " + a.getName() + "!" ;
}
- 결과값
- 위 방식 보다는 아래 방식이 더 좋다.
@GetMapping("/hello")
public String hello(Authentication a) {
return "Hello, " + a.getName() + "!" ;
}
# 비동기로 처리하는 경우
- @Async를 활용하여 자식 스레드를 생성하는 경우는 ThreadLocal을 인식하지 못한다.
- 이를 해결하기 위한 방안으로는 아래 코드와 같이 설정이 필요하다.
- 다만, 이는 @Async를 사용했을 경우에만 적용된다. Thread를 코드상으로 직접 생성해서 사용하면 기존의 ThreadLocal 처럼 인식하지 못한다.
@Bean
public InitializingBean initializingBean() {
return () -> SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL) ;
}