CORS

2024. 2. 24. 15:24Spring Boot

교차 출처 리로스 공유

Cross Origin Resource Sharing은

쉽게 말해 외부에서 내 서버의 리소스를 사용하는 것을 허가할 지에 대한 내용이다.

 

 

같은 https://localhost:5000에서 요청을 넣었기에 아무런 문제 없이 응답이 왔다

 

 

다른 곳에서 요청을 보내니 CORS policy 때문에 blocked 됬다고 에러가 났다

 

 

해결 방법은 Spring Security를 사용 중일 경우

 

http.cors(c -> c
            .configurationSource(corsConfig)
            );

 

 

filterchain에 위와 같이 설정을 추가하면 된다.

 

전체 코드는 

 

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import org.springframework.security.web.header.writers.frameoptions.XFrameOptionsHeaderWriter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.web.cors.CorsConfigurationSource;

import com.example.demo.jwt.jwtAuthenticationFilter;
import com.example.demo.jwt.jwtAuthorizationFilter;
import com.example.demo.jwt.jwtProvider;
import com.example.demo.oauth.CustomOAuth2Service;
import com.example.demo.redis.redis_repository;
import com.example.demo.user.customAuthenticationFilter;

import lombok.RequiredArgsConstructor;

import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;

@Configuration
@EnableWebSecurity
@RequiredArgsConstructor
@EnableMethodSecurity(
    prePostEnabled = true, 
    securedEnabled = true, 
    jsr250Enabled = true
    )
public class SecurityConfig {

    @Autowired
    private CustomOAuth2Service customoAuth2Service;
    
    @Autowired
    private final jwtProvider tokenProvider;

    
    @Qualifier("corsConfig")
    @Autowired
    CorsConfigurationSource corsConfig;

    @Autowired
    redis_repository repoR;

    @Bean
    SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http.cors(c -> c
            .configurationSource(corsConfig)
            );

        http.httpBasic((basic) -> basic.disable());
        http.apply(new jwtDsl(tokenProvider));
        http.apply(new sessionDsl());
        http.logout((logout) -> logout
            .logoutUrl("/user/logout/session")
            .logoutSuccessUrl("/"));

        http.sessionManagement((session) ->
            session
                .sessionCreationPolicy(SessionCreationPolicy.ALWAYS));

        http.csrf((csrf) -> csrf
            .ignoringRequestMatchers(new AntPathRequestMatcher("/form/**")));
        
        http.headers((headers) -> headers
            .addHeaderWriter(new XFrameOptionsHeaderWriter(
                XFrameOptionsHeaderWriter.XFrameOptionsMode.SAMEORIGIN)));

        http.oauth2Login((oauth) -> oauth
            .loginPage("/")
            .userInfoEndpoint((userInfoEndpoint) -> userInfoEndpoint
                .userService(customoAuth2Service)));
                
        return http.build();
    }

    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    public class jwtDsl extends AbstractHttpConfigurer<jwtDsl, HttpSecurity> {

        private final jwtProvider jwtProvider;

        public jwtDsl(jwtProvider jwtProvider) {
            this.jwtProvider = jwtProvider;
        }
		@Override
		public void configure(HttpSecurity http) throws Exception {
			AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
            jwtAuthenticationFilter filter = new jwtAuthenticationFilter(authenticationManager, jwtProvider);
            filter.setFilterProcessesUrl("/user/login/jwt/auth");
			http
            .addFilter(new jwtAuthorizationFilter(authenticationManager, jwtProvider))
            .addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
		}
	}

    public class sessionDsl extends AbstractHttpConfigurer<sessionDsl, HttpSecurity> {
		@Override
		public void configure(HttpSecurity http) throws Exception {
			AuthenticationManager authenticationManager = http.getSharedObject(AuthenticationManager.class);
            customAuthenticationFilter filter = new customAuthenticationFilter(authenticationManager, repoR);
            filter.setFilterProcessesUrl("/user/login/session/auth");
            http.
            addFilterBefore(filter, UsernamePasswordAuthenticationFilter.class);
		}
	}
}

 

import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

@Configuration
public class CorsConfig {

    @Bean
    @Qualifier("corsConfig")
    public CorsConfigurationSource corsConfigurationSource() {
      UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
      CorsConfiguration config = new CorsConfiguration();
      config.setAllowCredentials(true);
      config.addAllowedOriginPattern("*");
      config.addAllowedHeader("*");
      config.addAllowedMethod("*");

      source.registerCorsConfiguration("/**", config);
      return source;
   }

}

 

깔끔하게 정리하기 위해
굳이 CorsConfigurationSource를 따로 정의 했지만
그냥 SecurityConfig안에 정의해서 써도 된다. 

 

'Spring Boot' 카테고리의 다른 글

Authorization by Spring Security  (0) 2024.02.28
Jpa 순환 참조 N + 1 문제  (0) 2024.02.27
Naver Login  (0) 2024.02.19
Web Socket By STOMP  (0) 2024.02.19
Redis Pub/Sub  (0) 2024.02.19