서버

Spring boot) security모듈 있을 때와 없을 때 config처리방식(cors, csrf)

탐훈 2024. 8. 15. 20:36
728x90

개요)

spring boot 모듈 중

security 모듈을 추가하게 되면

config 처리를 다르게 해주어야 한다.

 

security 모듈이 없을 때 cors 처리와

security 모듈이 있을 때 cors 처리를 살펴보자

 


config 설정하는 파일은 두개다

 

1. CustomServletConfig.java

2. RootConfig.java

 

CustomServletConfig.java 파일은 

CORS처리 할 내용이 담긴 파일이다.

 

CORS는 Cross Origin Resource Sharing이다.

CORS가 일어났다는 의미는

"리소스가 교차 공유가 일어났다" 는 의미이다. 

 

예를 들어보자

내가 로컬로 프론트 서버, 백엔드 서버를 켰다.

프론트 포트번호는 8080

백엔드 포트번호는 8081

 

브라우저 입장에서는

프론트 서버, 백엔드 서버 

두 개의 출처에서 리소스를 공유하고 있다.

 

신뢰할 수 없다.

그래서 백엔드 서버로 요청 후 응답을 받을 때 

CORS 에러를 낸다.

 

백엔드 서버에 CORS 에러를 내는 이유는

프론트에서 백엔드로 요청하기 때문이다.


 

[CustomServletConfig.java]

@Configuration
public class CustomServletConfig implements WebMvcConfigurer {
    
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new LocalDateFormatter());
    }

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
        .allowedOrigins("*")
        .allowedMethods("HEAD", "GET", "POST", "PUT", "DELETE", "OPTIONS")
        .maxAge(300)
        .allowedHeaders("Authorization", "Cache-Control", "Content-Type");
    }
}

 

 

 

[RootConfig.java]

@Configuration
public class RootConfig {
    
    @Bean
    public ModelMapper getMapper() {
        ModelMapper modelMapper = new ModelMapper();
        modelMapper.getConfiguration()
                    .setFieldMatchingEnabled(true)
                    .setFieldAccessLevel(org.modelmapper.config.Configuration.AccessLevel.PRIVATE)
                    .setMatchingStrategy(MatchingStrategies.LOOSE);
        return modelMapper;
    }
}

 

여기에서는 CORS와는 관계 없는 설정이다. 

 

ModelMapper에 대한 클래스를 

사용할 때 커스텀하여 사용할 수 있다.

 

설정한 값의 의미는 아래와 같다.

setFieldMatchingEnabled: 키값과 맞춰서 넣어라

setFieldAccessLevel: private로 설정하라

setMatchingStrategy: Property랑 완전히 똑같이 하지 않고 느슨하게 해라

 


Security 모듈을 import 한 이후 처리는 다음과 같다.

 

디렉토리 구조는 아래 사진과 같다.

 

 

[CustomServletConfig.java]

package org.zerock.mailapi.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.format.FormatterRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import org.zerock.mailapi.controller.formatter.LocalDateFormatter;

@Configuration
public class CustomServletConfig implements WebMvcConfigurer {
    
    @Override
    public void addFormatters(FormatterRegistry registry) {
        registry.addFormatter(new LocalDateFormatter());
    }

    // securityConfig에서 추가로 인해 사용안함
    // @Override
    // public void addCorsMappings(CorsRegistry registry) {
    //     registry.addMapping("/**")
    //     .allowedOrigins("*")
    //     .allowedMethods("HEAD", "GET", "POST", "PUT", "DELETE", "OPTIONS")
    //     .maxAge(300)
    //     .allowedHeaders("Authorization", "Cache-Control", "Content-Type");
    // }
}

 

Security 모듈 이전에는

CustomServletConfig.java 파일에서 

CORS 처리를 했다.

 

Security 모듈을 추가하면서

Security에서 제공하는 모듈에서 설정해줘야 한다.

 

 

 


[CustomSecurityConfig.java]

package org.zerock.mailapi.config;

import java.util.Arrays;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;

@Configuration
@Log4j2
@RequiredArgsConstructor
public class CustomSecurityConfig {
    
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        log.info("--------------------- security  config ----------------");

        http.cors(httpSecurityConfigurer -> {
            httpSecurityConfigurer.configurationSource(configurationSource());
        });
        
        http.sessionManagement(sessionConfig -> sessionConfig.sessionCreationPolicy(SessionCreationPolicy.STATELESS));

        http.csrf(config -> config.disable()); // csrf 는 get 방식을 제외한 모든 요청에 "CSRF토큰"을 사용. 테스트 중에는 안하는 걸로 변경

        return http.build();
    }

    @Bean
    public CorsConfigurationSource configurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();

        configuration.setAllowedOriginPatterns(Arrays.asList("*"));
        configuration.setAllowedMethods(Arrays.asList("HEAD", "GET", "POST", "PUT", "DELETE"));
        configuration.setAllowedHeaders(Arrays.asList("Authorization", "Cache-Control", "Content-Type"));
        configuration.setAllowCredentials(true);

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);

        return source;
    }

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