다오의 개발일지

TIL-17 스프링 시큐리티 프레임워크 본문

WTIL

TIL-17 스프링 시큐리티 프레임워크

다오__ 2023. 6. 26. 16:17

'Spring Security' 프레임워크는 Spring 서버에 필요한 인증 및 인가를 위해 많은 기능을 제공해 줌으로써 개발의 수고를 덜어 줍니다. 마치 'Spring' 프레임워크가 웹 서버 구현에 편의를 제공해 주는 것과 같습니다.

 

'Spring Security' 프레임워크 추가

그리고 우리가 기존에 만들었던 Filter가 방해를 할 수가 있기때문에 @Component 를 주석처리 해줍니다.

 

스프링 시큐리티를 사용해서 인증, 인가를 편리하게 하기 위한 기본적인 설정들을 해줘야 합니다.

config 패키지에 아래의 설정 클래스를 만듭니다.

@Configuration
@EnableWebSecurity // Spring Security 지원을 가능하게 함
public class WebSecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        // CSRF 설정
        http.csrf((csrf) -> csrf.disable());

        http.authorizeHttpRequests((authorizeHttpRequests) ->
                authorizeHttpRequests
                        .requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() // resources 접근 허용 설정
                        .anyRequest().authenticated() // 그 외 모든 요청 인증처리
        );

        // 로그인 사용
        http.formLogin(Customizer.withDefaults());

        return http.build();
    }
}

1. csrf.disable()) - csrf에 대해서 사용하지 않음

2. HttpRequests.requestMatchers(PathRequest.toStaticResources().atCommonLocations()).permitAll() -

    StaticResources, atCommonLocations (리소스)에 대한 모든 접근 허옹

      (즉 resources폴더 안에 들어오는 요청들을 전부 다 허가 해줄 수 있는 것입니다.)

3. anyRequest().authenticated() 그 외의 모든 요청은 인증처리를 해야함

 

우리가 시큐리티를 사용할때 어떤 URL은 인가 하고 어떤 URL은 인가하지 않는 설정들을 해줘야 합니다.

이것은 여러가지 기능들을 사용 할지 안할지 또한 설정들을 해주는 메서드입니다.

 

HttpSecurity객체 http를 이용해서 우리가 필요한, 원하는 설정들을 전부 한 다음에 .build()하여 리턴을 하면 그 객체가 Bean으로 등록이 됩니다.

 

그러면 내부적으로 사용하면서 우리가 설정한 이 설정 값들이 시큐리티 프레임워크에 적용이 됩니다.

 

 

1. 시큐리티는 세션방식

스프링 시큐리티는 로그인을 하는순간 SessionID가 발급이 되고 시큐리티 내부에 세션 정보가 저장이 됩니다.

그리고 저장된 SessionID로 요청이 오면은 서버에서 비교를 해서 인증처리를 해줍니다.

즉 시큐리티는 세션방식으로 동작을 합니다.

 

2. 스프링 시큐리티 Filter Chain 기반 동

스프링에서 모든 호출은 디스패처서블릿을 통과하게 되고 이후에  요청을 담당하는 컨트롤러로 분배됩니다.

이때 각 요청에 대해서 공통적으로 처리해야할 필요가 있을 때 디스패처 서블릿 이전에 단계가 필요하며,

이것이 필터입니다.

 

  • Spring Security도 인증 및 인가를 처리하기 위해 Filter를 사용하는데
    • Spring Security는 FilterChainProxy를 통해서 상세로직을 구현하고 있습니다.

3. Form Login 기반은 인증

  • Form Login 기반 인증은 인증이 필요한 URL 요청이 들어왔을 때 인증이 되지 않았다면 로그인 페이지를 반환하는 형태입니다.

 

4. UsernamePasswordAuthenticationFilter

  • UsernamePasswordAuthenticationFilter는 Spring Security의 필터인 AbstractAuthenticationProcessingFilter를 상속한 Filter입니다.
  • 기본적으로 Form Login 기반을 사용할 때 username 과 password 확인하여 인증합니다.
  • 인증 과정
    1. 사용자가 username과 password를 제출하면 UsernamePasswordAuthenticationFilter는 인증된 사용자의 정보가 담기는 인증 객체인 Authentication의 종류 중 하나인 UsernamePasswordAuthenticationToken을 만들어 AuthenticationManager에게 넘겨 인증을 시도합니다.
    2. 실패하면 SecurityContextHolder를 비웁니다.
    3. 성공하면 SecurityContextHolder에 Authentication를 세팅합니다.

SecurityContextHolder

SecurityContextHolder 안의 SecurityContext 안의 Authentication이 담깁니다.

따라서 Authentication에 UsernamePasswordAuthenticationToken을 여기에 담으면 됩니다.

  • SecurityContext는 인증이 완료된 사용자의 상세 정보(Authentication)를 저장합니다.
  • SecurityContext는 SecurityContextHolder 로 접근할 수 있습니다.
// 예시코드
SecurityContext context = SecurityContextHolder.createEmptyContext();
Authentication authentication = new UsernamePasswordAuthenticationToken(principal, credentials, authorities);
context.setAuthentication(authentication); // SecurityContext 에 인증 객체 Authentication 를 저장합니다.

SecurityContextHolder.setContext(context);

 

  • principal : 사용자를 식별합니다.
    • Username/Password 방식으로 인증할 때 일반적으로 UserDetails 인스턴스입니다.
  • 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());

 

UsernamePasswordAuthenticationToken는

  Authentication을 implements한 AbstractAuthenticationToken의 하위 클래스로, 인증객체를 만드는데 사용됩니다.

 

 

UserDetailsService는 username/password 인증방식을 사용할 때 사용자를 조회하고 검증한 후 UserDetails를 반환합니다. Custom하여 Bean으로 등록 후 사용 가능합니다.

 

검증된 UserDetails는 UsernamePasswordAuthenticationToken 타입의 Authentication를 만들 때 사용되며 해당 인증객체는 SecurityContextHolder에 세팅됩니다. Custom하여 사용가능합니다.

 

 

복잡하지만.. 이러한 과정을 통해서 인증된 객체를 집어넣는데. 이 행위 자체가 인증이 완료됐다라는 의미입니다.

 

인증흐름