Spring 서버에 필요한 인증 및 인가를 위해 많은 기능을 제공해 줌으로써 개발의 수고를 덜어줌
Spring 프레임워크가 웹 서버 구현에 편의를 제공해 주는 것과 같음
Filter 기반으로 동작
Session 방식으로 기본적으로 동작
기본 defalut 로그인 제공
공격자가 인증된 브라우저에 저장된 쿠키의 세션 정보를 활용하여 웹 서버에 사용자가 의도하지 않은 요청을 전달하는 것
CSRF 설정이 되어있는 경우 html에서 CSRF 토큰 값을 넘겨주어야 요청을 수신 가능
쿠키 기반의 취약점을 이용한 공격이기 때문에 REST 방식의 API에서는 disable 가능
POST 요청마다 처리해주는 대신 CSRF protection을 disable
Spring에서 모든 호출은 DispatcherServlet을 통과하게 되고 이후에는 각 요청을 담당하는 Controller로 분배
이 때, 각 요청에 대해서 공통적으로 처리해야할 필요가 있을 때 DispatcherServlet 이전에 단계가 필요하며 이것이 Filter
Spring Security도 인증 및 인가를 처리하기 위해 Filter 사용
Spring Security의 필터인 AbstractAuthenticationProcessingFilter를 상속한 Filter
기본적으로 Form Login 기반을 사용할 때 username과 password 확인하여 인증
인증 과정
사용자가 username과 password를 제출
UsernamePasswordAuthenticationFilter는 인증된 사용자의 정보가 담기는 인증 객체인 Authentication의 종류 중 하나인 UsernamePasswordAuthenticationToken을 만듦
AuthenticationManager에게 넘겨 인증을 시도
실패하면 SecurityContextHolder를 비움
성공하면 SecurityContextHolder에 Authentication를 세팅
인증이 완료된 사용자의 상세 정보(Authentication)를 저장
SecurityContext는 SecurityContextHolder로 접근할 수 있음
// 예시코드
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
context.setAuthentication(authentication); // SecurityContext 에 인증 객체 Authentication 를 저장합니다.
SecurityContextHolder.setContext(context);
SecurityContext context 생성
createEmptyContext() : 비어 있는 Context를 만듦
Authentication authentication : 인증 객체를 만듦
생성된 인증된 객체를 context.setAuthentication하면서 넣어줌
만들어진 Context를 Holder에 다시 담아야함
SecurityContextHolder.setContext(context); : 보관소인 SecurityContextHolder에 Context를 담아야함
현재 인증된 사용자를 나타내며 SecurityContext에서 가져올 수 있음
principal : 사용자 식별
credentials : 주로 비밀번호, 대부분 사용자 인증에 사용한 후 비움
authorities : 사용자에게 부여한 권한을 GrantedAuthority로 추상화하여 사용
<UserDetails>
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
UserRoleEnum role = user.getRole();
String authority = role.getAuthority();
SimpleGrantedAuthority simpleGrantedAuthority = new SimpleGrantedAuthority(authority);
Collection<GrantedAuthority> authorities = new ArrayList<>();
authorities.add(simpleGrantedAuthority);
return authorities;
}
Authentication authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
username/password 인증 방식을 사용할 때 사용자를 조회하고 검증한 후 UserDetails 반환
Custom하여 Bean으로 등록 후 사용 가능
검증된 UserDetails는 UsernamePasswordAuthentication Token 타입의 Authentication를 만들 때 사용
해당 인증 객체는 SecurityContextHolder에 세팅 됨
Custom하여 사용 가능