Cors filter / Origin null is not allowed by Access-Control-Allow-Origin Chrome
IT노트/eGov&Spring F/W 2015. 3. 2. 21:57하이브리드 앱에서 서버에 ajax호출을 하다 보면 항상 cross origin 이슈가 발생한다. 하이브리드 앱은 html, javascript를 앱에 내장하는 경우가 많기 때문이다. 또한 개발할때도 로컬파일을 웹 브라우저로 열어서 작업하면 동일한 이슈가 발생한다.
그래서 구글링을 하면 개발할때 간단한 웹서버에 올리고 하라는 글들이 많다. 하지만 이렇게 한 것은 하이브리드 앱으로 배포하면 어차피 문제가 다시 발생하므로 적절하지 않다.
그래서 최근에는 JSONP를 많이 사용하는 추세인 것 같다. 특히 sencha touch 2에서는 JSONP를 API레벨로 지원하여 클라이언트 단에서는 그냥 ajax를 호출하는 것과 별 차이가 없다. 하지만 이렇게 하려면 서버쪽에서는 응답처리하는 곳에서 변경이 필요하고, API를 범용적으로(앱에서 직접 호출, 서버에서 호출 등) 만드는 데 제한이 생겨버린다. (JSONP는 결국 응답이 javascript 함수여야 한다. 물론 javascript 함수에서 json, xml등을 사용하지만 일단 클라이언트에서 응답을 열어보면 javascript 함수이므로 앱/서버 등에서 직접호출하는 방식에 적합하지 않다. 물론 공통 후처리 로직에서 파라미터를 보고 그냥 json으로 응답을 주거나 JSONP형식으로 주는 식의 구현을 통해서 비즈니스 로직은 공유할 수는 있을 것이다)
그래서 일반적인 json 요청/응답구조이면서 로컬 파일에서 ajax를 이용하여 서버로 통신하는 상황에서 cross origin 문제를 해결하는 방법들을 찾아 보았다. jquery를 보면 클라이언트 단에서 스크립트로 처리할 수 있는 $.support.cors 와 같은 것이 있는 데, jquery를 쓴다는 전제가 있을때에만 의미가 있고 이것을 써도 PC 크롬브라우저에서는 문제가 해결되지 않는다.(iOS, Android 하이브리드 앱에서는 위 옵션으로 서버와 통신이 잘 된다)
관련해서 서버에서 문제를 해결하는 방법을 찾아보니 http://www.w3.org/wiki/CORS_Enabled 이러한 사이트가 친절하게 정리가 되어 있었다. 물론 서버에서 해결하는 방법이기 때문에 손을 댈 수 없는 외부 서버와 클라이언트에서 직접 연동할때는 사용할 수 없다. (이글의 목적은 하이브리드 앱으로 개발하여 배포할 때, 서버와의 통신에 관련된 이슈 해결이다.)
테스트 환경이 tomcat이었으나, 7.0.4 버전이 아닌 관계로 저 사이트에 있는 cors filter를 쓸 수 없어서 spring controller 소스에
response.addHeader("Access-Control-Allow-Origin", "*");
와 같이 넣어서 테스트를 했다. 일단 사파리 브라우저에서 잘 되었다.
그런데, 크롬 브라우저에서는 Origin null is not allowed by Access-Control-Allow-Origin 메시지가 나오면서 안된다. 구글링을 열심히 했더니 --allow-file-access-from-files 옵션을 줘야 한다는 글들이 눈에 띄었다. 맥에서 이 옵션을 주고 띄우는 방법도 나와 있어서 했으나 문제는 여전했다(이건 말그대로 로컬 파일에서 다시 로컬파일을 읽어오는 것을 허용하는 것 같다). 다시 검색하니 --disable-web-security 옵션을 쓰라는데, 이 옵션을 주고 띄웠더니 지원하지 않는 옵션이라고 나온다.
뭔가 이런 문제가 아닌 것 같아서 파이어폭스에서 실행해보니까 역시 제대로 안된다. 크롬과 파이어폭스 개발도구에서 보니까 POST요청을 보내기 전에 OPTIONS 메소드를 보내는 것을 확인했다. 그래서 spring controller 메소드 어노테이션에 RequestMethod.OPTIONS 도 받게 추가했는 데, 제대로 안된다.
곰곰히 생각해보니 spring mvc controller는 servlet이 아니고, servlet에서 호출되는 것인데 @RequestBody가 선언이 되어 있으니 Content-Type이 application/json이 아니면 이 메소드로 들어오지 않는다.(OPTIONS 메소드로 호출할때는 Content-Type이 text/plain으로 호출되며 사실 body에 데이터는 없다) 그렇다고 json으로 요청받고 json으로 응답주는 서버에서 MVC까지 쓰면서 servlet 처럼 일단 받아서 내부에서 분기처리 및 기타 처리를 한다는 것은 좀 아닌 것 같다.
결국 인터넷에서 cors filter로 검색하여 http://software.dzhuvinov.com/cors-filter.html 사이트에서 jar를 받아서 적용을 하니 문제가 해결이 되어 크롬, 파이어폭스 모두 다 잘된다. (참고로 cors filter로 검색하면 eBay/cors-filter · GitHub 도 나온다)
아. 처음부터 HTTP 요청보고 문제를 해결하는 쪽으로 방향을 잡았으면 금새 해결했을텐데, 괜히 크롬관련 글들을 읽고 이것 저것 하느라 시간을 낭비했다.
'IT노트 > eGov&Spring F/W' 카테고리의 다른 글
스프링 Scheduler (0) | 2015.03.04 |
---|---|
스프링 프레임워크 강좌 (0) | 2015.02.20 |
EJB design pattern free book download (0) | 2015.02.18 |
AOP(Aspect Oriented Programmin) (0) | 2015.01.30 |
[IOC 제어의 역전] (0) | 2015.01.30 |