CORS?
- 교차 출처 자원 공유(Cross-Origin Resource Sharing)
- 한 출처의 웹 애플리케이션이 다른 출처의 자원에 접근하는 권한을
브라우저
에서 허용하게 하는 HTTP 헤더 기반 메커니즘
Origin
- URL의
Protocol
,Host
,Port
를 통해 같은 출처인지 다른 출처인지 판단할 수 있다.
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) |
Protocol ==
,Host ==
,Port ==
Protocol ==
,Host ==
,Port ==
Protocol ==
,Host ==
,Port !=
➡ IE 브라우저는Port
가 달라도 같은 출처로 처리한다.Protocol !=
,Host ==
,Port ==
Protocol ==
,Host !=
,Port ==
Protocol ==
,Host ==
,Port !=
➡ IE 외 브라우저는Port
가 다르면 다른 출처로 처리한다.
CORS Scenarios
- Request의
Origin
헤더 == Response의Access-Control-Allow-Origin
헤더 ➡ 같은 출처로 처리한다.
Preflighted Requests
Options
메소드로 예비 요청을 전송하여 본 요청을 전송하기에 안전한지 확인한다.- 예비 요청에서
- Request의
Origin
== Response의ACAO
면 같은 출처로 처리하여 본 요청을 수행한다. - Request의
Origin
!= Response의ACAO
면 다른 출처로 처리하여 본 요청을 수행하지 않는다.
- Request의
브라우저
에서 같은 출처인지 다른 출처인지 판단하기 때문에서버
는 200대의 성공 코드를 반환한다.
Simple Requests
- 예비 요청이 없고, 예비 요청이 했던 행동을 본 요청에서 전부 처리한다.
- 제약사항이 많다.
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
- 보안을 더 강화시킨 시나리오이다.
Cookie
를 담을 수 있게Option
을 준다. ➡서버
는 인증된 사용자인지 한 번 더 확인한다.
- 제약사항이 있다.
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;
}
}
- CORS 정책 설정파일에
CorsConfigurationSource
등록- 이 부분을 생략하면 CORS 정책을 설정하는 의미가 없다.
- CORS 정책 설정 Bean
addAllowedOrigin()
➡ 허용 URL을 지정한다.addAllowedHeader()
➡ 허용 Header를 지정한다.addAllowedMethod()
➡ 허용 Method를 지정한다.