Spring Security) Spring Security 기초

Dokuny·2022년 1월 11일
0

Spring Security

목록 보기
4/7

Spring Security란

스프링 기반 애플리케이션의 보안을 담당해주는 프레임워크이다. 서블릿 필터를 기반으로 이루어져있으며 보안과 관련된 많은 옵션을 제공해주기 때문에 개발자들은 보안 로직 보다는 주 로직에 관심을 쏟을 수 있게 도와준다.

용어 설명

  • Authentication(인증) : 보호된 리소스에 접근하는 대상, 즉 사용자에게 적절한 접근 권한이 있는지 확인하는 절차
  • Authorization(인가) : 인증된 사용자가 요청한 자원에 접근 가능한지 결정하는 절차
  • Principal(접근 주체) : 보호된 리소스에 접근하는 대상
  • Credential(비밀 번호) : Principal의 비밀번호
  • 권한 : 인증된 주체가 어플리케이션의 동작을 수행할 수 있도록 허락되어 있는지를 결정

참고사항

  • 기본적으로 Spring Security는 인증 절차를 거친 후 인가 절차를 진행하며 ,인가 과정에서 해당 리소스에 대한 접근 권한이 있는지를 확인한다. 이러한 인증,인가를 위해 Principal을 아이디로,Credential을 비밀번호로 사용하는 인증방식을 사용한다.
  • 인증 정보는 최종적으로 인메모리 세션 저장소인 SecurityContextHolder에 세션-쿠키 방식으로 저장된다.

구조

Form Login 절차

1. 요청 수신

사용자가 아이디(username)비밀번호(password) 를 입력하고 인증 요청을 보냄

2. 토큰 생성

AuthenticationFilter가 요청을 가로챈 후, 가로챈 정보를 통해 UsernamePasswordAuthenticationToken이라는 인증용 객체생성

  • UsernamePasswordAuthenticationToken 내부의 principal 에는 아이디를, credentials에는 비밀번호를 넣어 둔다.

UsernamePasswordAuthenticationToken(=Authentication 객체)타입은 해당 요청을 처리할 수 있는 Provider을 찾는데 사용(4번 참고)

  • Form Login(id,password) 방식의 AuthenticationFilter는 UsernamePasswordAuthentication Filter로 id,password 방식의 인증일 때 사용되는 필터이다.
  • id,password 방식이 아닌 OAuth2.0이나 JWT 인증은 이 필터가 아닌 다른 필터를 거치게 된다.

3. Authentication Manager에게 처리 위임

AuthenticationFilter는 생성한 UsernamePasswordAuthenticationToken을 AuthenticationManager에게 전달

4. Token을 처리할 수 있는 Authentication Provider 선택

AuthenticationManager는 List형태AuthenticationProvider들을 갖고 있다.

구현체ProviderManager가 갖고 있는 AuthenticationProvider들을 차례로 탐색하면서 각 Provider들의 supports(Class<?> authentication) 메소드를 호출하여 Authentication 타입 확인UsernamePasswordAuthenticationToken를 전달

  • 폼 로그인 시에 Provider의 default 값으로 DaoAuthenticationProvider가 작동한다고 들은 것 같다.
  • 직접 AuthenticationProvider를 커스터마이징 한 구현 객체를 사용할 수도 있다.
@Override
public boolean supports(Class<?> authentication) {
    // 이런 식으로 Provider가 Authentication의 타입을 검증하여 해당 타입이 맞다면 그 Provider로 실행
    return authentication.equals(UsernamePasswordAuthenticationToken.class);

}

5. UserDetailsService에 정보 전달

AuthenticationProvider는 실제 데이터베이스에서 사용자 인증정보를 가져오는 UserDetailsService사용자 정보(아이디,username) 를 전달

6. DB등 사용자의 정보가 저장 된 곳에서 데이터를 꺼내어 UserDetails형태로 반환

UserDetailsService를 구현하여 loadUserByUsername(String username)를 오버라이딩

loadUserByUsername메소드에서 넘겨받은 사용자 정보를 통해 DB에서 사용자 정보를 찾는 로직을 작성하고 찾은 사용자 정보를 담은 UserDetails 객체를 만들어 반환

  • UserDetails는 인터페이스기 때문에 직접 구현을 한 객체를 반환하던가,미리 구현해놓은 User 객체를 반환해도 된다.

  • 인증용 객체(예를 들어 UserDetails를 구현한 객체)와 도메인 객체(실제 정보를 담은 Entity)를 분리하지 않기 위해서 실제 사용되는 도메인 객체에 UserDetails를 상속하기도 한다.

7. Authentication Provider에서 사용자 정보 비교

Authentication Provider가 데이터베이스에서 반환 받은 정보(UserDetails)와 Http Request를 통해 들어온 로그인 정보를 비교한다.

8. 9. 인증 완료된 Authentication 객체를 반환

인증이 완료되면 권한 등의 사용자 정보를 담은 Authentication 객체를 반환한다.

10. Authentication객체를 SecurityContextHolder안에 저장


Spring Security Filter

스프링 시큐리티는 훨씬 다양한 필터체인을 사용하여 다양한 커스터마이징을 할 수 있는데, 모든 필터를 다 외우고 있을 필요는 없고 간략하게 뭐가 있는지만 확인해두고 필요할 때 제대로 찾아보면 될 것 같다.

  • SecurityContextPersistentFilter : SecurityContextRepository에서 SecurityContext를 가져와서 SecurityContextHolder에 주입하거나 반대로 저장하는 역할을 합니다.

  • LogoutFilter : logout 요청을 감시하며, 요청시 인증 주체(Principal)를 로그아웃 시킵니다.

  • UsernamePasswordAuthenticationFilter : login 요청을 감시하며, 인증 과정을 진행합니다.

  • DefaultLoginPageGenerationFilter : 사용자가 별도의 로그인 페이지를 구현하지 않은 경우, 스프링에서 기본적으로 설정한 로그인 페이지로 넘어가게 합니다.

  • BasicAuthenticationFilter : HTTP 요청의 (BASIC)인증 헤더를 처리하여 결과를 SecurityContextHolder에 저장합니다.

  • RememberMeAuthenticationFilter : SecurityContext에 인증(Authentication) 객체가 있는지 확인하고 RememberMeServices를 구현한 객체 요청이 있을 경우, RememberMe를 인증 토큰으로 컨텍스트에 주입합니다.

  • AnonymousAuthenticationFilter : 이 필터가 호출되는 시점까지 사용자 정보가 인증되지 않았다면 익명 사용자로 취급합니다.

  • SessionManagementFilter : 요청이 시작된 이후 인증된 사용자인지 확인하고, 인증된 사용자일 경우 SessionAuthenticationStrategy를 호출하여 세션 고정 보호 매커니즘을 활성화 하거나 여러 동시 로그인을 확인하는 것과 같은 세션 관련 활동을 수행합니다.

  • ExceptionTranslationFilter : 필터체인 내에서 발생되는 모든 예외를 처리합니다.

  • FilterSecurityInterceptor : AccessDecisionManager로 권한부여처리를 위임하고 HTTP 리소스의 보안 처리를 수행합니다.

Authentication 객체

Principal은 Authentication 객체(위 설명에선 UsernamePasswordAuthenticationToken) 를 생성한다. 이 객체는 SecurityContext에 보관되어 사용된다.

public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities(); // Authentication 저장소에 의해 인증된 사용자의 권한 목록
    Object getCredentials(); // 비밀번호
    Object getDetails(); // 사용자 상세정보
    Object getPrincipal(); // ID
    boolean isAuthenticated(); //인증 여부
    void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}

참고사항

  • Authentication : 사용자 ID, 패스워드와 인증 요청 컨텍스트에 대한 정보를 가지고 있다. 인증 이후의 사용자 상세정보와 같은 UserDetails 타입 오브젝트를 포함할 수도 있다.
  • UserDetails : 이름, 이메일, 전화번호와 같은 사용자 프로파일 정보를 저장하기 위한 용도로 사용한다.

reference

profile
모든 것은 직접 경험해보고 테스트하자

0개의 댓글