Uncaught DOMException: Blocked a frame with origin "https://pac.domain.com"
from accessing a cross-origin frame.
Uncaught SecurityError: Failed to read a named property 'parentSomethingProperty'
on 'Window': Blocked a frame with origin "https://pac.domain.com"
from accessing a cross-origin frame.
μ μμ μΌλ‘ μ§νλλ κ²°μ μμ κ°μκΈ° μμ κ°μ μλ¬λ‘ κ²°μ κ° λΆκ°λ₯ν μν©μ΄ λ°μνμ΄μ. μ½λκ° λ³κ²½λ κ²λ μμλλ° κ°μκΈ° μ μ΄λ° μλ¬κ° λ°μλμμκΉμ?
μμ μλ¬ λ©μμ§λ₯Ό νμΈν΄λ³΄λ©΄ https://pac.domain.com μ£Όμμ μ κ·Όμ΄ μ°¨λ¨λμλ€λ κ²μ νμΈν΄λ³Ό μ μμ΄μ. μ¬κΈ°μ ν¬μΈνΈλ cross-orgin
μ΄λΌλ λ©μμ§μμ.
cross-origin
μ΄λ κ΅μ°¨ μΆμ²λ₯Ό λ»νκ³ CORS(Cross Origin Resource Sharing)
λ κ΅μ°¨ μΆμ²μμμ μμ 곡μ λ₯Ό λ»ν΄μ. κ·Έλ λ€λ©΄ μΆμ²λ 무μμΌκΉμ?
https://leeseo.mydomain.com:443/post/search?page=1#CORSλ
https://
: Protocolleeseo.mydomain.com
: Host443
: Port(μλ΅ κ°λ₯)/post/search
: Path?page=1
: Query String#CORSλ
: Fragmentμμ URLμμ Protocol
, Host
, Port
μ΄ 3κ°μ§κ° λμΌν λ λμΌ μΆμ²(Same-origin)
λΌκ³ ν΄μ.
λ§μ½ Protocol, Host, Port μ€ λ¨ νλλΌλ λ€λ₯΄λ€λ©΄ κ΅μ°¨ μΆμ²(Cross-origin)
λ‘ κ°μ£ΌλΌμ.
κΈ°μ‘΄ μλ²μΈ‘ μ½λμμλ CORSμ κ΄ν μ½λκ° μ΄λ―Έ μμ±λμ΄ μμμ΄μ. κ·ΈλΌμλ λΆκ΅¬νκ³ μμ κ°μ κ΅μ°¨ μΆμ² λ¬Έμ κ° λ°μλκ³ μμμ΄μ.
μ°λ¦¬κ° λ§μ΄ μ νλ CORSλ νλ‘ νΈμ λ°±μλ μλ²μ ν΅μ μμ κ΅μ°¨ μΆμ²λ‘ μΈν΄ λ°μλλ μ΄μκ° λ§μμ΄μ. μ΄λ‘μΈν΄ CORSμ κ΄λ ¨λ κ²μμ νλ©΄ λλΆλΆ νλ‘ νΈμ μλ²μ ν΅μ μμ μλ²μ CORS ν΄μ λ°©λ²κ³Ό κ΄λ ¨ν μ λ³΄λ§ λ§μ΄ λμ ν΄λΉ μ΄μμ μμΈμ νμ νλλ° μ΄λ €μμ΄ μμμ΄μ.
μ ν¬λ μ€νλ§ λΆνΈ(Spring Boot)μ μ€νλ§ μν리ν°(Spring Security)λ₯Ό μ¬μ© μ€μ΄μλλ° ν΄λΉ κ΄λ ¨ μ 보λ μ λΆ μ€νλ§ μν리ν°μμ CORS κ΄λ ¨ μ€μ νλ λ°©λ²μ΄λ μ€νλ§μμ μ§μνλ @CrossOrigin
μ νμ©νλ λ°©λ²λ§ λμμ΄μ.
λ°λΌμ κ΄μ μ λ¬λ¦¬νκ³ μ²μμΌλ‘ λμκ° ν΄λΉ λ¬Έμ μ λν κ·Όλ³Έμ μΈ μμΈμ λ€μ νμ ν΄λ³΄κΈ°λ‘ νμ΄μ.
μμΈμ λΆμν λ κ΅μ°¨ μΆμ²λΌλ μλ¬ λ©μμ§μ λ΄μ©λ§μΌλ‘ νλ¨νμ¬ ν΄κ²°νλ € νλ κ²μ΄ ν¨μ°©μ΄μμ΄μ. λ°λΌμ κΈ°μ‘΄ μ½λλ₯Ό λ€μ λΆμνκΈ°λ‘ νμ΄μ.
μ ν¬μ κ²°μ μμ€ν μ μλμ κ°μ μνμ€λ‘ ꡬμ±λμ΄ μμ΄μ. μ΄ν΄λ₯Ό λκΈ° μν΄ Pathλ κ΄λ ¨ λ°μ΄ν° μΈν λ° μμΈμ²λ¦¬ λ±μ μλ΅νλλ‘ ν κ²μ.
// μ°μ λΉ νμ
μ μ€νν΄μ.
window.open('about:blank', 'pay-popup', 'width=600,height=400');
// μλ°μ€ν¬λ¦½νΈλ₯Ό ν΅ν΄ λμ μΌλ‘ λ§λ€μ΄ νΈμΆν μλ μμ΄μ.
// μ΄ν΄λ₯Ό λκΈ° μν΄ htmlλ‘ μμ±ν κ²μ.
// 1μ°¨μ μΌλ‘ κ²°μ μ κ΄λ ¨ν λ°μ΄ν°λ₯Ό μ
ν
ν΄μ.
// μ ν¬ κ²°μ μλ²μ λ°μ΄ν°λ₯Ό μ μ‘νλ formμ μμ±ν΄μ.
<form id="pay" action="https://pac.mydomain.com/requestPay" style="display: none;">
<input id="info1" name="info1" value="info1" />
</form>
// pay-popupμ΄ pac.mydomain.comμΌλ‘ μ΄λλΌμ.
document.getElementByid("pay").submit();
<form id="pay-request" action="https://www.payment.com/blabla" style="display: none;">
// κ²°μ μ κ΄λ ¨λ λ°μ΄ν° μ
ν
<input id="returnUrl"
name="returnUrl"
value="https://pac.mydomain.com/returnPay"
/>
</form>
// νΌ λ°©μμΌλ‘ νμ¬ νμ
μμ λ²€λμ¬μ κ²°μ νμ΄μ§λ₯Ό μμ²(submit)ν΄μ.
document.getElementById('pay-request').submit();
// κ²°μ μλ΅μ΄ μ±κ³΅μΌ κ²½μ° mydomain.comμ μλ
// successPaymentλ₯Ό νΈμΆνμ¬ κ²°μ μλ£ νμ΄μ§λ‘ μ΄λν΄μ.
parent.successPayment(data);
λ¬Έμ λ 4λ²μμ λ°μλμμ΄μ. λ§μ½ νλ‘ νΈμ μλ²μ κ΅μ°¨ μΆμ² λ¬Έμ μλ€λ©΄ κ²°μ μλ²μ μ‘΄μ¬νλ μ€νλ§ μν리ν°μμ CORS κ΄λ ¨ ν΄μ μ½λλ‘ ν΄κ²°μ΄ λμμ κ±°μμ. νμ§λ§ μμ λ¬Έμ λ νλ‘ νΈμ λ°±μλ ν΅μ μμ λ°μνλ CORS λ¬Έμ κ° μλλΌ νμ μμ λΆλͺ¨ νμ΄μ§μ μμμ μ κ·Όν λ λ°μλλ κ΅μ°¨ μΆμ² λ¬Έμ μμ΄μ.
μ°λ¦¬ ννμ΄μ§(λΆλͺ¨ νμ΄μ§)λ mydomain.com
μΈλ° κ²°μ μλ²(νμ
)λ pac.mydomain.com
μΌλ‘ ꡬμ±λμ΄ μκΈ° λλ¬Έμ κ΅μ°¨ μΆμ²κ° λ°μλμ΄ νμ
μμ λΆλͺ¨ νμ΄μ§μ μλ successPayment
ν¨μλ₯Ό νΈμΆνμ§ λͺ»νλ κ²μ΄μμ£ . (MSA κ΅¬μ‘°λ‘ ννμ΄μ§ μλ²μ κ²°μ μλ²κ° λΆλ¦¬λμ΄ μμ΄μ.)
νμ§λ§ μ κ°μκΈ° κ΅μ°¨ μΆμ² λ¬Έμ κ° λ°μλμμκΉμ? κΈ°μ‘΄μλ μ μ μμ μΌλ‘ κ²°μ κ° μ§ν λμμκΉμ?
κΈ°μ‘΄ μ½λμμλ κ΅μ°¨ μΆμ² λ¬Έμ λ₯Ό ν΄κ²°νκΈ° μν΄ κ²°μ μλ²μ μλ°μ€ν¬λ¦½νΈμμ document.domain
μ Setterλ₯Ό ν΅ν΄ ν΄κ²°νκ³ μμμ΄μ.
document.domain
μμ±μ λλ©μΈ μ΄λ¦μ μ€μ νκ±°λ κ°μ Έμ¬ μ μλ DOM μμ±μ΄μμ. μ΄λ₯Ό ν΅ν΄ λΆλͺ¨-μμ μ°½ κ°μ μλ‘ λ€λ₯Έ λλ©μΈμ λμΌν λλ©μΈμΌλ‘ μ€μ ν¨μΌλ‘μ¨ λμΌ μΆμ² μ μ±
(Same-Origin Policy) μ νμ νΌν μ μμμ΄μ. μλμ κ°μ μ½λλ‘ λ§μ΄μ£ .
docuemnt.domain = "mydomain.com"
μμ κ°μ΄ domainμ βmydomain.comβ μΌλ‘ μμ νκ² λλ©΄ μλ‘ λ€λ₯Έ μλΈ λλ©μΈ(Subdomain)μ κ°μ§μ§λ§ λμΌν eTLD+1(mydomain.com)μ κ°μ§κ² λμ΄ λ μΆμ²λ₯Ό λμΌ μΆμ²μΈ κ²μ²λΌ μ·¨κΈμ΄ κ°λ₯νμ΄μ.
λ¨, μμ κ²½μ°μλ κΈ°λ³Έ λλ©μΈ μμ²΄κ° λ€λ₯Έ κ²½μ°μλ μ μ©μ΄ λΆκ°λ₯ν΄μ.
μ1. ) pac.mydomain.com μ documnet.domain = βmydomain.comβ
μΌλ‘ λ³κ²½ κ°λ₯
μ2. ) pac.super-mydomain.comμ document.domain = βmydomain.comβ
μΌλ‘ λ³κ²½ λΆκ°
μ3. ) super-mydomain.comμ document.domain = βmydomain.comβ
μΌλ‘ λ³κ²½ λΆκ°
νμ§λ§ document.domain setterλ μλμ κ°μ λ¬Έμ μ μ κ°μ§κ³ μμ΄μ.
μ΄λ¬ν λ¬Έμ μ μΌλ‘ μΈν΄ Chrome 115 λ²μ λΆν°λ document.domainμ λ³κ²½ν μ μκ² λμμ΄μ. ν¬λ‘¬λΏλ§ μλλΌ λ€λ₯Έ λΈλΌμ°μ λ μ μ°¨ ν΄λΉ κΈ°λ₯μ μ 곡νμ§ μμ μμ μ΄μμ.
Chrome 115λΆν° μ§μ μ€λ¨
MDN Deprecated
μ΄λ κ² μ μ°¨ λΈλΌμ°μ μμ μ λ°μ΄νΈλ¨μ λ°λΌ document.domain Setterκ° λμνμ§ μκ² λμκ³ , μ΄λ‘ μΈν΄ μ΄λ€ κ³ κ°μ μ μμ μΌλ‘ μ§νλκ³ μ΅μ λΈλΌμ°μ λ²μ μ μ¬μ©νλ κ³ κ°μ μ μ μ§νμ΄ λΆκ°λ₯νλ κ²μ΄μμ΄μ. λꡬλ μ μ μ§νμ΄ λκ³ , λꡬλ μ μ μ§νμ΄ λΆκ°λ₯νλ μ΄μ κ° μ¬κΈ°μ μμλ κ²μ΄μμ£ .
μ¬λ΄PCμμ ν΄λΉ νμ ꡬνκ³Ό νμ μ΄ μ΄λ €μ λ μ΄μ λ 보μ μ μ± μ νμλ§μΌλ‘ μ΄λ£¨μ΄μ Έ ꡬλ²μ λΈλΌμ°μ λ₯Ό μ΄μ©νκΈ° λλ¬Έμ μμΈμ λͺ¨λ₯΄λ μνμμ μ΄μ νμ μ λ μ΄λ €μ λ€κ³ μ¬λ£λΌμ. μ΄λ‘ μΈν΄ μΈλΆλ§μμλ§ ν΄λΉ νμμ΄ κ΅¬νλλ μ΄μ λ μ€λͺ μ΄ λμμ£ . (2024.01.03 μΈλΆλ§ Chrome Version: 120.0.6099.130)
νμλ§μΌλ‘ μΈν Google Chrome μλ λ° μλ μ λ°μ΄νΈ λΆκ°λ₯ν μν.
μ΄λ¬ν κ΅μ² μΆμ²μμ μμ νκ² λμΌ μΆμ² μ μ±
μ μ½ μ‘°κ±΄μ μ°νν μ μλ κΈ°λ₯μ μλ°μ€ν¬λ¦½νΈμμλ window.postMessage()
μ ν΅ν΄ μ 곡νκ³ μμ΄μ. ν΄λΉ ν¨μλ λΆλͺ¨ νμ΄μ§μμ μμ±λ νμ
κ°μ ν΅μ μ΄λ, νμ΄μ§μ νμ΄μ§ μμ iframe κ°μ ν΅μ μμ μ¬μ©ν μ μμ΄μ.
// λ°©λ² 1.
window.onmesage = (event) => {
console.log(event);
};
// λ°©λ² 2.
window.addEventListener('message', (event) => {
console.log(event);
});
// λ°©λ² 3. Object dataλ₯Ό λ°λ λ°©λ²
window.onmessage = (event) => {
console.log(JSON.parse(event.data));
};
event κ°μ²΄ νλ‘νΌν°
data
: μ λ¬ λ°μ λ°μ΄ν°.origin
: postMessage κ° νΈμΆλ λ λ©μμ§λ₯Ό 보λ΄λ μλμ°μ origin.source
: λ©μμ§λ₯Ό λ³΄λΈ window μ€λΈμ νΈμ λν μ°Έμ‘°.// κΈ°λ³Έ λ¬Έλ²
targetWindow.postMessage(message, targetOrigin, [transfer]);
// string μ μ‘
targetWindow.postMessage('message');
// κ°μ²΄ μ μ‘
const data = { message: 'my message' };
targetWindow.postMessage(JSON.stringify(data));
// targetOrigin μ§μ
targetWindow.postMessage('message', 'https://mydomain.com');
targetWindow
: λ©μμ§λ₯Ό μ λ¬ λ°μ windowμ μ°Έμ‘°.message
: λ€λ₯Έ windowμ 보λ΄μ§ λ°μ΄ν°.targetOrigin
: targetWindowμ originμ μ§μ . β*βμΌ κ²½μ° λ³λλ‘ μ§μ νμ§ μμμ μλ―Έ.// λΆλͺ¨ νμ΄μ§
const popup = window.open('about:blank', 'pay-popup', 'width=600,height=400');
// λ°μ΄ν° μ
ν
ν submit, ν¬μ€ν
μλ¨ λΆλΆ μμ μ°Έμ‘°
window.onmessage((event) => {
if (event.origin !== 'https://pac.mydomain.com') return;
const { code, data } = JSON.parse(event.data);
if (code !== 'success') return;
successPayment(data);
});
function successPayment(data) {
// κ²°μ νμ²λ¦¬ λ‘μ§
}
// μ°Έκ³ . λ§μ½ λΆλͺ¨ νμ΄μ§μμ νμ
μ λ©μμ§λ₯Ό μ λ¬νκ³ μΆμ κ²½μ°.
// popup.postMessage('message');
// νμ
const data = {
code: 'success',
data: { ... }, // μλ΅
};
opener.postMessage(JSON.stringify(data));
window.postMessage()
μ¬μ© λ°©λ²μ λν΄μ λμ± μμΈν μ€λͺ
μ μλ λ§ν¬μμ νμΈ κ°λ₯ν΄μ.
Window.postMessage() - Web API | MDN
ν루 νκ· μ½ 2,000 ~ 3,000 건 λ‘κ·Έ μ μ¬
2024.01.02 00:00:00 ~ 2024:01.02 23:59:59 κΈ°μ€: 3,074 건
2024.01.03 17:00:00 ~ 2024:01.04 15:00:00 κΈ°μ€: 0건
μλ λ§ν¬μμ ν¬μ€ν μμ λ€λ£¨μλ μ 보λ₯Ό λ³΄λ€ μμΈνκ² νμΈν μ μμ΄μ.