[Spring Security] 시큐리티 동작 원리

OOSEDUS·2024년 9월 23일

스프링 시큐리티

목록 보기
1/4
post-thumbnail

https://www.youtube.com/watch?v=y0PXQgrkb90&list=PLJkjrxxiBSFCKD9TRKDYn7IE96K2u3C3U&index=1
"개발자 유미" 님의 시큐리티 시리즈를 보고 정리합니다.
현 글은 위 영상을 보고 정리하였습니다

시큐리티 동작 원리

  1. 클라이언트의 요청이 Sevlet Container에 들어온다.
  2. 해당 요청이 접근하려는 Spring Boot 내의 Controller에 권한이 있는지 몇가지의 필터링을 거친다.
  3. Spring Security Config를 등록해두면 특정한 필터를 만들어서 필터링을 한다.
    EX-1) 로그인하는 경우, 모든 필터를 그냥 통과하게 하여 Login Controller로 진입하게 한다.
    EX-2) 마이페이지 접근 경우, Session에 접근하는 유저의 정보가 저장되어있는 경우 필터링을 통과하여 해당 Controller로 진입하게 된다.

인증
시큐리티를 통해 인증을 진행하는 방법은 사용자가 Login 페이지를 통해 아이디, 비밀번호를 POST 요청시 스프링 시큐리티가 DB에 저장된 회원 정보를 조회 후 비밀번호를 검증하고 서버 세션 저장소에 해당 아이디에 대한 세션을 저장한다.


인가
Spring Security가 필터에서 아래 내용을 검증한다.

  • 해당 경로의 접근이 누구에게 열려있는지
  • 로그인이 완료된 사용자인지
  • 해당되는 ROLE을 가지고 있는지

Security Config

  • 아래 코드에서 @EnableWebSecurity 어노테이션을 붙임으로써 해당 클래스가 Spring Security 한테서도 관리가 된다.

  • @Bean 어노테이션을 붙인 메소드를 등록하여서 자동으로 커스텀 필터를 만들어서 사용할 수 있다.

  • SecurityFilterChain 의 리턴 타입을 가지고 HttpSecurity라는 메소드 인자를 받는다.

  • authorizeHttpRequests 를 통해 특정 경로에다가 요청을 허용 및 거부가 된다. (스프링부트 버전 3.1.x 이상은 작성 방식은 람다식으로 해야한다)

  • requestMachers() : 특정 경로 및 경로에 대한 권한을 설정하는 메소드

  • permitAll() : 로그인을 하지 않아도 모든 사용자에 대해 열려있다.

  • hasRole() : 로그인한 후에 특정한 role이 있어야 한다.(ex. ADMIN)

  • authenticated() : 로그인하면 접근할 수 있다.

  • denyAll() : 로그인을 하더라도 모든 사용자가 접근할 수 없다.

  • anyRequest() : requestMachers()로 설정하지 않은 모든 경로를 말한다.

  • formLogin() : 만약 권한이 없는 접근을 했을때 자동으로 로그인 페이지로 갈 수 있게 설정하는 것

@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{

        http
                .authorizeHttpRequests((auth) -> auth
                        .requestMatchers("/", "/login", "/loginProc").permitAll()
                        .requestMatchers("/admin").hasRole("ADMIN")
                        .requestMatchers("/my/**").hasAnyRole("ADMIN", "USER")
                        .anyRequest().authenticated()
                );


        http
                .formLogin((auth) -> auth.loginPage("/login")
                        .loginProcessingUrl("/loginProc")
                        .permitAll()
                );

        http
                .csrf((auth) -> auth.disable());


        return http.build();
    }
}

**.requestMachers의 순서도 중요하다. 그래서 anyRequest()를 마지막에 두는 것 생각하기


회원가입 로직

  • 회원가입 시 role을 지정할때 ROLE_USER 와 같이 ROLE_ 를 붙여서 저장해야 한다.

UserDetailsService 인터페이스 구현

@Service
public class CustomUserDetailsService implements UserDetailsService {

    @Autowired
    private UserRepository userRepository;


    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        UserEntity userData = userRepository.findByUsername(username);

        if (userData != null) {

            return new CustomUserDetails(userData);
        }

        return null;
    }
}
  • Spring Boot 환경에서, UserDetailsService를 구현한 빈(예: CustomUserDetailsService)이 존재하면, Spring Security는 이를 자동으로 감지하고 AuthenticationProvider에 등록한다.

  • UserDetailsService는 사용자 정보를 가져오는 데 사용되는 인터페이스로, loadUserByUsername(String username) 메서드를 Override 함으로써 사용자의 상세 정보를 로드한다. 이 메서드는 UserDetails 객체를 반환해야 하며, Spring Security는 이 객체를 기반으로 인증을 수행한다.

즉, UserDeatilsService를 implements 하는 서비스를 통해 로그인하는 유저의 정보가 DB 에 있는지 확인한다.


Http Basic 인증 방식

Http Basic 인증 방식은 아이디와 비밀번호를 Base64 방식으로 인코딩한 뒤 HTTP 인증 헤더에 부착하여 서버측으로 요청을 보내는 방식이다.

  • 주로 내부망의 서버간 통신을 진행하는 경우 사용
  • 따로 로그인페이지 필요하지 않기 때문에 서버가 서버에게 로그인 진행할 때 사용한다.
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{

    http
            .httpBasic(Customizer.withDefaults());

    return http.build();
}
profile
성장 가능성 만땅 개발블로그

0개의 댓글