Spring Security CORS 설정
CORS - Cross Origin Resource Sharing
추가 HTTP 헤더를 사용하여, 한 출처에서 실행 중인 웹 애플리케이션이 다른 출처의 선택한 자원에 접근할 수 있는 권한을 부여하도록 브라우저에 알려주는 체제입니다. 웹 애플리케이션은 리소스가 자신의 출처(도메인, 프로토콜, 포트)와 다를 때 교차 출처 HTTP 요청을 실행합니다.
예시 )
https://domain-a.com의 프론트 엔드 JavaScript 코드가 Jquery를 사용하여
https://domain-b.com/data.json을 요청하는 경우
Client Request(localhost:1804 -> localhost:1814)
function corsTest(param) {
var requestUrl = "http://localhost:1814/corstes/"+param;
$.ajax({
url: requestUrl,
crossOrigin : true,
type: "GET",
beforeSend : function (xhr) {
xhr.setRequestHeader("Authorization", "Bearer " + token);
},
dataType : "json",
success: function(data) {
var test = JSON.stringify(data);
data.forEach(function (n){
});
},
error: function(request, status, error) {
console.log("code:" + request.status + "\n" + "message:" + request.responseText + "\n" + "error:" + error);
alert("error..");
}
});
}
Spring-Security를 사용중일때 CORS 적용방법
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers(HttpMethod.OPTIONS,"http://localhost:1814").permitAll() -- (1)
.anyRequest().authenticated()
.and()
.httpBasic();
http.cors(); -- (2)
}
-- (1)에 대한 설명 전 CORS preflight 요청 개념에 대해 알아야 한다.
CORS preflight
사실 기본적인 내용들은 모질라의 HTTP 접근제어(CORS) 문서에 잘 설명되어 있다.
상기 문서에 설명되어 있듯이 브라우저는 현재 웹페이지 이외의 사이트에 요청할 때 CORS preflight 라는 요청을 보낸다. 이 것은 실제 해당 서버에 CORS 정책을 확인하기 위한 요청이며 OPTIONS 메소드를 사용하여 요청을 보낸다 (GET /hello 요청에 대해 OPTIONS /hello 요청을 preflight로 먼저 보낸다).
이 OPTIONS 요청은 웹페이지의 javascript에 의한 명시적인 요청이 아니라, 브라우저가 알아서 보내는 요청이다.
이 요청의 응답으로 적절한 CORS 접근 권한을 얻지 못하면 브라우저는 그 사이트에 대한 xhr 요청을 모두 무시한다. (실제 서버응답을 javascript로 돌려주지 않는다)
--(1)
http://localhost:1814에서 오는 CORS preflight요청(HTTP OPTIONS 메소드)를 허락하겠다.
--(2)
Spring-Security에서 cors를 적용한다 라는 뜻, 인증 성공여부와 무관하게 Request Header 중 'Origin' 헤더가 있는 요청에 대해서 CORS 응답 헤더를 포함하여 response한다.
CORS Response에 대한 상세 설정
@Configuration
public class WebMvcConfig extends WebMvcConfigurerAdapter {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**")
.allowedOrigins("http://localhost:1814") -- (1)
.allowedMethods("GET") -- (2)
.allowedHeaders("Authorization") -- (3)
.allowCredentials(true).maxAge(3600); -- (4)
}
}
-- (1)
http://localhost:1814 에 대한 Origin만 허용한다.
-- (2)
HTTP Method 중 GET만 허용한다.
-- (3)
이부분은 테스트가 좀 필요한데 Client 단에 Authorization 헤더를 포함하여 요청해서 적어줬다.
--(4)부분에 allowCredentials(true)와 연관지어 해당 헤더를 포함해야 된다고 명시해준것.
-- (4)
allowCredentials(true)면 해당서버에서 Authorization으로 사용자 인증을 할거면 사용한다.
maxAge(3600) : preflight 요청의 캐시 시간.