Posts [Web] CORS
Post
Cancel

[Web] CORS

CORS?

  • 교차 출처 자원 공유(Cross-Origin Resource Sharing)
  • 한 출처의 웹 애플리케이션이 다른 출처의 자원에 접근하는 권한을 브라우저에서 허용하게 하는 HTTP 헤더 기반 메커니즘

Origin

origin_example

  • URL의 Protocol, Host, Port를 통해 같은 출처인지 다른 출처인지 판단할 수 있다.
 
같은 출처
다른 출처
https://github.com
1. https://github.com/da-nyee
2. https://github.com/da-nyee?tab=repositories
3. https://github.com:8080 ➡ IE (O)
4. http://github.com
5. https://api.github.com
6. https://github.com:8080 ➡ IE (X)
  1. Protocol ==, Host ==, Port ==
  2. Protocol ==, Host ==, Port ==
  3. Protocol ==, Host ==, Port != ➡ IE 브라우저는 Port가 달라도 같은 출처로 처리한다.
  4. Protocol !=, Host ==, Port ==
  5. Protocol ==, Host !=, Port ==
  6. Protocol ==, Host ==, Port != ➡ IE 외 브라우저는 Port가 다르면 다른 출처로 처리한다.

CORS Scenarios

  • Request의 Origin 헤더 == Response의 Access-Control-Allow-Origin 헤더 ➡ 같은 출처로 처리한다.

Preflighted Requests

preflighted_reqs

  • Options 메소드로 예비 요청을 전송하여 본 요청을 전송하기에 안전한지 확인한다.
  • 예비 요청에서
    • Request의 Origin == Response의 ACAO면 같은 출처로 처리하여 본 요청을 수행한다.
    • Request의 Origin != Response의 ACAO면 다른 출처로 처리하여 본 요청을 수행하지 않는다.
  • 브라우저에서 같은 출처인지 다른 출처인지 판단하기 때문에 서버는 200대의 성공 코드를 반환한다.

Simple Requests

simple_reqs

  • 예비 요청이 없고, 예비 요청이 했던 행동을 본 요청에서 전부 처리한다.
  • 제약사항이 많다.
    • Request-Method, Allow-Methods 허용 종류
      • GET
      • HEAD
      • POST
    • Request-Headers, Allow-Headers 허용 종류
      • Accept
      • Accept-Language
      • Content-Language
      • Content-Type
      • DPR
      • Downlink
      • Save-Data
      • Viewport-Width
      • Width
    • Content-Type 허용 종류
      • application/x-www-form-urlencoded
      • multipart/form-data
      • text/plain

Credentialed Requests

credentialed_reqs

  • 보안을 더 강화시킨 시나리오이다.
  • Cookie를 담을 수 있게 Option을 준다. ➡ 서버는 인증된 사용자인지 한 번 더 확인한다.
Option
Description
same-origin (default)
같은 출처간 요청에만 인증 정보를 담는다.
Include
모든 요청에 인증 정보를 담는다.
Omit
모든 요청에 인증 정보를 담지 않는다.
  • 제약사항이 있다.
    • ACAO* 와일드 카드를 사용할 수 없다. ➡ 명시적인 URL을 지정해야 한다.
    • Response에 반드시 Access-Control-Allow-Credentials: true가 존재해야 한다.

CORS with Spring Security

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
@RequiredArgsConstructor
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    private final JwtTokenProvider jwtTokenProvider;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .httpBasic().disable()
                .cors().configurationSource(corsConfigurationSource())  ---------- 1.
                .and()
                    .csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
                .and()
                    .authorizeRequests()
                        .antMatchers("/api/v1/shops/**").hasRole("OWNER")
                        .antMatchers(HttpMethod.PUT, "/api/v1/users/**").hasAnyRole("USER", "OWNER")
                        .antMatchers(HttpMethod.DELETE, "/api/v1/users/**").hasAnyRole("USER", "OWNER")
                        .antMatchers(HttpMethod.GET, "/api/v1/users/").hasAnyRole("USER", "OWNER")
                        .anyRequest().permitAll()
                .and()
                    .addFilterBefore(new JwtAuthenticationFilter(jwtTokenProvider),
                            UsernamePasswordAuthenticationFilter.class);


    }

    @Bean --------- 2.
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration configuration = new CorsConfiguration();

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

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", configuration);
        return source;
    }
 }
  1. CORS 정책 설정파일에 CorsConfigurationSource 등록
    • 이 부분을 생략하면 CORS 정책을 설정하는 의미가 없다.
  2. CORS 정책 설정 Bean
    • addAllowedOrigin() ➡ 허용 URL을 지정한다.
    • addAllowedHeader() ➡ 허용 Header를 지정한다.
    • addAllowedMethod() ➡ 허용 Method를 지정한다.

Refereneces

This post is licensed under CC BY 4.0 by the author.