여러 다른 url을 가진 사이트간의 통신은 cross-domain 보안 정책에 의해 기본적으로 차단되어 있는 상황에서 보안정책을 변경하는 것 보단 간단한 메시지를 전달하는 정도의 방식으로 프로그래밍을 하는 것이 수월하기에 iframe을 이용해 서로 다른 도메인간의 통신을 유도하는 방법을 찾아보았습니다.
일단 메시지를 보내는 주 사이트와, 메시지를 받는 사이트 측으로 분리해서 아래와 같은 스크립트를 만들어보았습니다.
크로스 도메인을 위한 스크립트 구성
부모페이지에 추가된 script (메시지를 받는 쪽)
//iframe를 첨부할 jsp 내에 아래와 같은 스크립트와 iframe을 추가합니다.
<script type="text/javascript">
//iframe에서 전송하는 메시지를 받을 리스너를 생성
//(iframe과 동일한 페이지 현재 스크립트가 있어야함)
function receiveMessage(event){
//리스너 이벤트 전송자와, 명령어가 동일할 경우 수행
if(event.data === "testMessage" && event.origin === "http://testsite"){
//event.data는 리스너를 통해 전달받는 데이터입니다.
// ===은 데이터 타입과 데이터 내용이 모두 일치하는지 비교하는 연산자
//event.origin은 지정된 주소를 입력하여 지정된 도메인에서 발신한 것인지 확인합니다.
alert("메시지 전달 받았습니다.");//메시지 수신 후 실행할 스크립트를 입력합니다.
}
}
//현재창에 메시지 이벤트 리스너를 추가
window.addEventListener("message", receiveMessage);
</script>
//현재창에 메시지 이벤트 리스너를 추가
<iframe id="test" name="test" src="http://testsite/innerFrame.jsp"></iframe>
<script type="text/javascript">
//iframe에서 전송하는 메시지를 받을 리스너를 생성
//(iframe과 동일한 페이지 현재 스크립트가 있어야함)
function receiveMessage(event){
//리스너 이벤트 전송자와, 명령어가 동일할 경우 수행
if(event.data === "testMessage" && event.origin === "http://testsite"){
//event.data는 리스너를 통해 전달받는 데이터입니다.
// ===은 데이터 타입과 데이터 내용이 모두 일치하는지 비교하는 연산자
//event.origin은 지정된 주소를 입력하여 지정된 도메인에서 발신한 것인지 확인합니다.
alert("메시지 전달 받았습니다.");//메시지 수신 후 실행할 스크립트를 입력합니다.
}
}
//현재창에 메시지 이벤트 리스너를 추가
window.addEventListener("message", receiveMessage);
</script>
//현재창에 메시지 이벤트 리스너를 추가
<iframe id="test" name="test" src="http://testsite/innerFrame.jsp"></iframe>
메시지를 주는 쪽인 http://testsite/의 innerFrame.jsp
<script type="text/javascript">
var parent = window.parent;
if(parent && parent.postMessage){
//postMessage("전송메시지","전송 도메인")
parent.postMessage("testMessage", "*");
}else{
console.log("post Message is not allow");
}
</script>
var parent = window.parent;
if(parent && parent.postMessage){
//postMessage("전송메시지","전송 도메인")
parent.postMessage("testMessage", "*");
}else{
console.log("post Message is not allow");
}
</script>
위와 같은 비교적 단순한 구성을 통해 서로 다른 도메인 간의 메시지를 주고받을 수 있습니다.
postMessage 함수는 메시지와 함께 전송할 대상 도메인을 특정할 수 있습니다. 이유는 불필요한 도메인에서 해당 소스를 붙여 메시지를 가로채거나 하는 문제를 방지하기 위해서 입니다.
이 스크립트는 iframe내부 문서와 부모창의 구성을 바꿔서 사용할 수도 있습니다.
postMessage구성
postMessage(메시지, 대상도메인)메시지 : 다른 창으로 보낼 데이터를 담는 부분입니다. (구조화된 복제 알고리즘을 통해 정해진 양식으로 변형되어 전송된다고 합니다. )
대상도메인 : "*"을 입력한경우 대상을 특정하지 않고 아무에게나 보내는 것입니다. 공개된 메시지가 되는 것이므로, 중요한 데이터를 보내면 위험할 수 있습니다. 아무나 iframe을 사용하여 메시지를 확인할 수 있으니까요.
사용 예) document.postMessage("메시지", "http://test.kr") 의 형태로 메시지를 보낼경우 http://test.kr이 아닌 도메인에선 해당 메시지를 확인할 수 없습니다.
SANDBOX
HTML5에서는 SANDBOX라는 속성이 생겼습니다. 이것을 이용해 크로스도메인 정책을 우회할 수 있다는 인터넷의 일부 문서를 확인했습니다만. 적용결과 실패하였습니다. 안됩니다.
샌드박스 속성과 값
1. (값없음) 모든 제한 사항 적용2. allow-forms 폼 전송을 사용할 수 있습니다.(form.submit())
3. allow-pointer-lock api를 사용할 수 있습니다.
4. allow-popups 팝업을 사용할 수 있습니다.
5. allow-same-origin iframe내부의 콘텐츠가 같은 도메인으로 취급됩니다.
6. allow-scripts 스크립트를 사용할 수 있습니다.
7. allow-top-navigation iframe 내부 콘텐츠가 top.document의 location을 제어할 수 있습니다.
위와 같은 태그 속성이 있고 iframe을 선언할 때 사용하는 코드입니다. 사용방법은 아래와 같습니다.
1. (값없음) <iframe sandbox src=""> </iframe>
2. allow-forms <iframe sandbox="allow-forms" src=""> </iframe>
3. 복합 <iframe sandbox="allow-forms allow-top-navigation" src=""> </iframe>
단일 속성을 사용할 수도 있고, 복합 속성을 사용할 수도 있습니다. allow-same-origin 의 경우 서로 다른 도메인일 경우에도 같은 출처로 취급할 수 있다고 설명되어있지만, 실제 사용결과는 다음 오류가 발생합니다.
예) iframe 내에서 top.window.document.reload()를 수행한경우 오류
Uncaught DOMException: Blocked a frame with origin "" from accessing a cross-origin frame.
도메인이 다르기 때문에 발생하는 오류입니다. 이것이 postMessage를 사용하게 된 이유이기도 합니다. 같은 도매인 내에서의 iframe호출은 성공적이었지만, 서로 다른 도메인에 적용한 결과 위와 같은 오류가 발생하여 사용할 수 없습니다.
w3schools에서는 모든 브라우저에서 적용된다고 되어있지만, 실제로 되지 않고 있습니다. 이유를 아시는 분이 계신다면 댓글을 달아주시면 감사하겠습니다.
댓글 없음:
댓글 쓰기