본문 바로가기

Language/Spring Security

사용자 정의 보안 설정하기

728x90

사용자 정의 보안 기능 구현

  • 한 개 이상의 SecurityFilterChain 타입의 빈을 정의한 후 인증 API 및 인가 API 설정
    • 인증 API
      • http.formLogin()
      • http.logout()
      • http.csrf()
      • http.httpBasic()
      • ...
    • 인가 API
      • http.authorizeHttpRequests(auth -> auth.requestMatchers(/admin)
      • .hasRole(USER)
      • .permitAll()
      • .authenticated()
      • ...

기본 구현 코드

@EnableWebSecurity
@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .formLogin(Customizer.withDefaults());
        return http.build();
    }
}

 

  • @EnableWebSecurity를 클래스에 정의
  • 모든 설정 코드는 람다 형식으로 작성
    → 스프링 시큐리티 7버전 이후 람다 형식만 지원예정
  • SecurityFilterChain을 빈으로 정의하면 자동 설정에 의한 SecurityFilterChain은 생성되지 않음

기본 자동 설정 미실행 직접 확인

  • SpringBootWebSecurityConfiguration의 defaultSecurityFilterChain() 메서드에 중단점 체크하여 디버그로 실행
    → 실행되지 않음 확인

  • 이유 (프로젝트 생성 / 의존성 추가에서 설명)


사용자 추가 설정 (둘 중 하나 선택)

  • application 파일에 설정
spring:
  security:
    user:
      name: user
      password: 1111
      roles: USER

 

  • 자바 설정 클래스에 직접 정의
@Bean
public UserDetailsService userDetailsService(){
    UserDetails user = User.withUsername("user")
            .password("{noop}1111")
            .roles("USER")
            .build();
    return new InMemoryUserDetailsManager(user);
}

 

  • application 설정과 자바 설정이 겹치게 될 경우 자바 설정이 더 우선 순위
    → application.properties(yml) < 자바 설정
  • 여러 유저 한 번에 등록 가능
@EnableWebSecurity
@Configuration
public class SecurityConfig {
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http
                .authorizeHttpRequests(auth -> auth.anyRequest().authenticated())
                .formLogin(Customizer.withDefaults());
        return http.build();
    }
    @Bean
    public UserDetailsService userDetailsService(){
        UserDetails user = User.withUsername("user")
                .password("{noop}1111")
                .roles("USER")
                .build();
        UserDetails user2 = User.withUsername("user2")
                .password("{noop}2222")
                .roles("USER")
                .build();
        UserDetails user3 = User.withUsername("user3")
                .password("{noop}3333")
                .roles("USER")
                .build();
        return new InMemoryUserDetailsManager(user, user2, user3);
    }
}
  • 유저 이름이 겹쳐졌을 경우 에러 발생 withUsername()
    → username 중복 불가
@Bean
public UserDetailsService userDetailsService(){
    UserDetails user = User.withUsername("user")
            .password("{noop}1111")
            .roles("USER")
            .build();
    UserDetails user2 = User.withUsername("user")
            .password("{noop}2222")
            .roles("USER")
            .build();
    return new InMemoryUserDetailsManager(user, user2);
}

 

더보기

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.WebSecurityConfiguration': Unsatisfied dependency expressed through field 'httpSecurity': Error creating bean with name 'org.springframework.security.config.annotation.web.configuration.HttpSecurityConfiguration.httpSecurity' defined in class path resource [org/springframework/security/config/annotation/web/configuration/HttpSecurityConfiguration.class]: Failed to instantiate [org.springframework.security.config.annotation.web.builders.HttpSecurity]: Factory method 'httpSecurity' threw exception with message: Error creating bean with name 'userDetailsService' defined in class path resource [io/security/springsecuritymaster/SecurityConfig.class]: Failed to instantiate [org.springframework.security.core.userdetails.UserDetailsService]: Factory method 'userDetailsService' threw exception with message: user should not exist

728x90