티스토리 뷰

728x90
반응형

Spring Security..??


  • 스프링 시큐리티가 뭘까? 프로젝트에 스프링 시큐리티를 적용하면서 적용은 됬는데 어떠한 흐름인지, 어떻게 보안을 적용해주는지 조금 더 깊게 알아야하지 않을까? 라는 생각에 정리를 해볼려고 합니다.

 

Spring Security란


  • 스프링 시큐리티란 어플리케이션의 보안(인증 및 권한)을 담당하는 프레임 워크입니다.
  • Spring Security를 사용하지 않으면 자체적으로 세션을 사용하여 체크하던가 기타 다른 방법으로 체크를 해주어야 합니다.

 

Spring Security의 동작 위치


Tomcat
  • Tomcat은 서블릿 컨테이너라고도 불립니다. 이 Tomcat은 다양한 필터와 서블릿으로 구성되어 있습니다.
  • 웹 개발을 하면 Dispatcher Servlet 하위에 컨트롤러부터 시작하는 흐름을 보통 많이 다루는데 Spring Security는 필터 부분을 조작하게 됩니다.

 

Spring Security
  • Spring Security가 포함된 흐름입니다.
  • Spring Security는 여러가지 필터로 이루어져 있고 필터들이 순서대로 동작하게 됩니다. 이러한 구조를 Filter Chain 구조라고 합니다.

 

인증 - 인가


인증
  • 해당 사용자가 본인이 맞는지 확인하는 절차
인가
  • 인증된 사용자가 어떠한 경로에 접근이 가능한지 확인하는 절차
Spring Security에서의 인증 / 인가
  • Spring Security는 기본적으로 인증 절차를 거친 후 인가에  대한 절차를 진행하게 되며 인가 과정에서 해당 리소스에 대한 접근 권한이 있는지 확인을 하게 됩니다. Spring Security에서는 이러한 인증과 인가를 위해 Principal을 아이디로, Credential을 비밀번호로 사용하는 Credential 기반의 인증 방식을 사용합니다.

Principal(접근 주체) : 보호받는 리소스에 접근하는 대상

Credential(비밀번호) : 리소스에 접근하는 대상의 비밀번호

 

Spring Security의 구조


SecurityContextHolder
  • SecurityContextHolder는 보안 주체의 세부 정보를 포함하여 프로그램의 현재 보안 컨텍스트에 대한 세부 정보가 저장됩니다. 

 

SecurityContext
  • Authentication을 보관하는 역할을 하며 SecurityContext를 통하여 Authentication 객체를 꺼내올 수 있습니다.

 

Authentication
  • Authentication은 현재 접근하는 주체의 정보와 권한을 담은 인터페이스입니다. Authentication 객체는 SecurityContext에 저장되며 SecurityContextHolder를 통해 SecurityContext에 접근하고 SecurityContext를 통해 Authentication에 접근할 수 있습니다.

 

UsernamePasswordAuthenticationToken
  • UsernamePasswordAuthenticationToken은 Authentication을 implements한 AbstractAuthenticationToken의 하위 클래스로 User의 ID가 Principal의 역할이고 Password가 Credential의 역할을 합니다. UsernamePasswordAuthenticationToken의 첫번째 생성자는 인증전의 객체를 생성하고 두번재 생성자는 인증이 완료된 객체를 생성합니다.

 

AuthenticationProvider
  • AuthenticationProvider에서는 실제 인증에 대한 부분을 처리하는데 인증 전의 Authentication 객체를 받아서 인증이 완료된 객체를 반환하는 역할을 합니다. 

 

Authentication Manager
  • 인증에 대한 부분은 Spring Security의 AuthenticationManager를 통해서 처리되는데 실질적으로는 AuthenticationManager에 등록된 AuthenticationProvider에 의해 처리됩니다.

 

UserDetails
  • 인증에 성공하여 생성된 UserDetails 객체는 Authentication 객체를 구현한 UsernamePasswordAuthenticationToken을 생성하기 위해 사용됩니다. 

 

UserDetailsService
  • UserDetailsService 인터페이스는 UserDetails 객체를 반환하는데 loadUserByUsername() 메서드를 재정의하여 데이터베이스에서 유저가 있는지 확인합니다.

 

Spring Security Config 
@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final JwtProvider jwtProvider;
    private final WebAccessDeniedHandler webAccessDeniedHandler;
    private final AuthenticationEntryPointHandler authenticationEntryPointHandler;
    private final CustomUserDetailService customUserDetailService;

    @Override
    protected void configure(AuthenticationManagerBuilder builder) throws Exception {
        builder.userDetailsService(customUserDetailService).passwordEncoder(passwordEncoder());
    }

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Bean(name = BeanIds.AUTHENTICATION_MANAGER)
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    public void configure(WebSecurity web) {
        web.ignoring().antMatchers("/v2/api-docs",
                "/configuration/ui",
                "/swagger-resources/**",
                "/configuration/security",
                "/swagger-ui.html",
                "/webjars/**");
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .httpBasic().disable()
            .csrf().disable()
            .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
                .authorizeRequests()
                .antMatchers("/admin/**/**").hasRole("ADMIN")
                .antMatchers(HttpMethod.POST, "/app/**/write").hasRole("ADMIN")
                .antMatchers(HttpMethod.GET, "/app/user/**").hasRole("USER")
                .antMatchers("/app/auth/**").permitAll()
                .anyRequest().permitAll()
            .and()
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPointHandler)
                .accessDeniedHandler(webAccessDeniedHandler)
            .and()
                .addFilterBefore(new JwtAuthenticationFilter(jwtProvider), UsernamePasswordAuthenticationFilter.class);
    }
}
Configuration
  • 해당 클래스를 Configuration으로 등록합니다.

 

EnableWebSecurity
  • Spring Security를 활성화합니다.

 

configure(AuthenticationManagerBuilder) 메서드
  • Spring Security 사용시 어떠한 패스워드 암호화 방식을 사용해서 비교할건지 설정합니다.

 

AuthenticationManager authenticationManagerBean() 메서드
  • csrf()를 disable한 이유는 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(등록, 수정, 삭제) 등 요청하게 만들 수 있습니다.

 

configure(WebSecurity Web)
  • 정적 파일은 보안에 해당 사항이 없으므로 무시할 수 있도록 설정합니다.

 

configure(HttpSecurity http)
  • Security에 필요한 각종 설정을 합니다.

 

csrf().disable() : csrf => Cross-Site-Request Forgery
  • csrf()를 disable한 이유는 사용자가 자신의 의지와는 무관하게 공격자가 의도한 행위(등록, 수정, 삭제) 등 요청하게 만들 수 있습니다.

 

Spring Boot 에 스프링 시큐리티를 적용해보자!

 

Spring boot - security-jwt 연동과 흐름(feat.AccessToken, RefreshToken)

스프링 시큐리티는 뭘까? Spring boot - Spring Security에 대하여 Spring Security..?? 스프링 시큐리티가 뭘까? 프로젝트에 스프링 시큐리티를 적용하면서 적용은 됬는데 어떠한 흐름인지, 어떻게 보안을 적

kdg-is.tistory.com

 

728x90
반응형