TeamUp 프로젝트 (Spring Security + JWT 구현)

zirung-i·2024년 2월 27일

Spring Security

목록 보기
1/2

1. 프로젝트 환경

Spring Boot: 3.2.2
Spring Security: 3.2.2
JDK: 21

2. 프로젝트 초기 세팅

build.gradle

implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.springframework.boot:spring-boot-starter-security'

// JWT 관련 dependency
implementation 'io.jsonwebtoken:jjwt-api:0.12.5'
runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.12.5'
runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.12.5'

// lombok
compileOnly 'org.projectlombok:lombok'
annotationProcessor 'org.projectlombok:lombok'

// MariaDB
runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'

testImplementation 'org.springframework.boot:spring-boot-starter-test'
testImplementation 'org.springframework.security:spring-security-test'

3. JWT 세팅

SecurityConfig.java

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
public class SecurityConfig {
	private final JwtAuthenticationFilter jwtAuthenticationFilter;
    private final CustomAuthenticationEntryPoint authenticationEntryPoint;
    private final CustomAccessDeniedHandler accessDeniedHandler;
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    	http
                .cors((cors) ->
                        cors.configurationSource(corsConfigurationSource())
                )
                .csrf((csrf) ->
                        csrf.disable()
                )
                .sessionManagement((sessionManagement) ->
                        sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                )
                .authorizeHttpRequests((authorizeRequests) ->
                        authorizeRequests
                                .requestMatchers("/api/user", "/api/user/*").hasRole("FREE")
                                .requestMatchers("/api/auth", "/api/auth/*").permitAll()
                                .anyRequest().authenticated()
                )
                .formLogin((formLogin) ->
                        formLogin.disable()
                )
                .httpBasic((httpBasic) ->
                        httpBasic.disable()
                )
                .exceptionHandling((exceptionHandler) ->
                        exceptionHandler
                                .authenticationEntryPoint(authenticationEntryPoint)
                                .accessDeniedHandler(accessDeniedHandler)
                )
                ;
                
                http.addFilterBefore(jwtAuthenticationFilter, UsernamePasswordAuthenticationFilter.class);
                
                return http.build();
    }
    
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();

        configuration.addAllowedOrigin("*");
        configuration.addAllowedHeader("*");
        configuration.addAllowedMethod("*");
        configuration.setAllowCredentials(false);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
    
    @Bean
    public PasswordEncoder passwordEncoder() {
    	return new BCryptPasswordEncoder();
    }
    
}

cors.configurationSource(corsConfigurationSource())

  • cors에 대한 설정을 한다.
  • TODO: cors에 대한 내용을 다루는 문서 추가 필요
  • TODO: CorsConfigurationSource에서 어떤 옵션을 주는지 추가 필요

csrf.disable())

  • 이 프로젝트에서는 Session을 사용하지 않기 때문에 csrf 토큰을 받지 않아도 된다. 따라서 csrf를 비활성화 한다.
  • TODO: csrf에 대한 내용을 다루는 문서 추가 필요

sessionManagement.sessionCreationPolicy(SessionCreationPolicy.STATELESS)

  • JWT를 사용하여 사용자를 인증하기 때문에 세션을 사용하지 않도록 설정한다.

authorizeRequests.requestMatchers("/api/user").hasRole("ROLE")

  • 해당 URI로 요청할 수 있는 권한을 정의한다.

formLogin.disable()

  • form login 방식을 사용하지 않기 때문에 비활성화 한다.

httpBasic.disable()

  • httpBasic 인증을 받아야 하는 경우에만 접근할 수 있는 리소스에 접근하려고 하면 prompt 인증창이 표시된다. (참고)
  • JWT를 사용하기 때문에 httpBasic 관련 설정을 비활성화 한다.

exceptionHandler.authenticationEntryPoint(authenticationEntryPoint)

  • Spring Security의 Filter를 처리하는 중에 401 Unauthorized 에러가 발생하면 이 핸들러를 사용하여 예외를 처리한다.

exceptionHandler.accessDeniedHandler(accessDeniedHandler)

  • Spring Security의 Filter를 처리하는 중에 403 Forbidden 에러가 발생하면 이 핸들러를 사용하여 예외를 처리한다.

4.

profile
지렁지렁

0개의 댓글