로그인중 헤더 누락과 CORS에러 발생

jungnoeun·2023년 2월 1일
0

kiri

목록 보기
7/13

회원가입과 로그인을 구현하고,
프론트 팀원들과 코드를 맞춰보던중,
로그인 완료시, 몇가지 문제가 발생했다.
1. 다음의 헤더 내용이 누락되는 문제

  1. CORS 에러




해결과정

1번의 문제를 해결하기 위해,
구글링을 하며 여러가지 방법을 시도했다.

1. WebMvcConfig 설정 추가

// 스프링 서버 전역적으로 CORS 설정
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedMethods("*") // 허용할 HTTP METHOD
                .allowedOriginPatterns("*") // 허용할 출처
                .allowCredentials(true) // 쿠키 인증 요청 허용
                // ===========수정한 내용=====================
                .allowedHeaders("*")
                .exposedHeaders("Authorization"); // 반환하고싶은 헤더값
                // ===========수정한 내용=====================
    }
}

위와 같이 바꾼후 실행했지만, 실패하였다.




2. SecurityConfig 설정 추가

2-1) .cors()

@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
 //=======================추가한 부분=========================
                .cors()
                .and()
//=======================추가한 부분=========================
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .formLogin().disable()
                .httpBasic().disable()
                .apply(new MyCustomDsl()) // 커스텀 필터 등록
                .and()
                .logout()
                .logoutSuccessUrl("/login")

                .and()

                .authorizeRequests(authorize -> authorize
               	 .antMatchers("/api/posts/**","/calender/**","/extra/**","/member/**")
                        .authenticated()

                        .anyRequest() // 나머지 req들은 인증없이 허용
                        .permitAll()
                );

        return http.build();

    }

위의 내용을 시도했더니, 인증이 필요없는 회원가입 시도에도 403에러가 뜨며 실패하였다.



2-2) .cors(Customizer.withDefaults())

@Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
        http
                .csrf().disable()
 //=======================추가한 부분=========================
                .cors(Customizer.withDefaults())
//=======================추가한 부분=========================
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                .formLogin().disable()
                .httpBasic().disable()
                .apply(new MyCustomDsl()) // 커스텀 필터 등록
                .and()
                .logout()
                .logoutSuccessUrl("/login")

                .and()

                .authorizeRequests(authorize -> authorize
               	 .antMatchers("/api/posts/**","/calender/**","/extra/**","/member/**")
                        .authenticated()

                        .anyRequest() // 나머지 req들은 인증없이 허용
                        .permitAll()
                );

        return http.build();

    }

위의 내용을 시도했더니, 성공했다.
원하는 헤더의 3개의 내용도 잘 받아지고,
회원가입 시에도 잘 접근이 가능하고,
회원가입 완료또한 잘 되었으며,
로그인 완료 후 토큰 반환도 가능했다.



왜 이것이 가능했을까?


The easiest way to ensure that CORS is handled first is to use the CorsFilter. Users can integrate the CorsFilter with Spring Security by providing a CorsConfigurationSource that uses the following:

스프링 프레임워크는 CORS를 위한 first class support를 제공한다. CORS는 스프링 시큐리티 이전에 진행되어야 한다. 왜냐하면 preflight 요청은 어느 쿠키도 포함하고 있지 않기 때문이다. 만약 요청이 어느 쿠키도 포함되고 있지 않고, 스프링 시큐리티가 첫 요청이라면, 요청에 어떤 쿠키가 없기 때문에, 유저가 authenticated되어 있지 않다고 판단하고, 요청을 거부한다.

그래서 CORS를 허용할 가장 쉬운 방법은 CorsFilter를 사용하는 것이다. 사용자들은 CorsFilter를 스프링 시큐리티와 통합하여 사용할 수 있다. 그 방법은 CorsConfigurationSource를 제공하는 것이다.

예제 코드는 아래와 같다.

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {

	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
		http
			// by default uses a Bean by the name of corsConfigurationSource
			.cors(withDefaults())
			...
		return http.build();
	}

	@Bean
	CorsConfigurationSource corsConfigurationSource() {
		CorsConfiguration configuration = new CorsConfiguration();
		configuration.setAllowedOrigins(Arrays.asList("https://example.com"));
		configuration.setAllowedMethods(Arrays.asList("GET","POST"));
		UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
		source.registerCorsConfiguration("/**", configuration);
		return source;
	}
}

2-1의 방법은 스프링 시큐리티의 이전 버전이라고 한다.




참고>
https://docs.spring.io/spring-security/reference/servlet/integrations/cors.html
https://stackoverflow.com/questions/59760003/enabling-cross-origin-requests-spring-boot
https://velog.io/@subimm/SEBBE-65%EC%9D%BC%EC%B0%A8-JWT-%EC%9D%B8%EC%A6%9D2-Authentication#-jwt-%EC%9E%90%EA%B2%A9-%EC%A6%9D%EB%AA%85%EC%9D%84-%EC%9C%84%ED%95%9C-%EB%A1%9C%EA%B7%B8%EC%9D%B8-%EC%9D%B8%EC%A6%9D-%EA%B5%AC%ED%98%84

profile
개발자

0개의 댓글