所以我想到了这个可能的解决方案。我称之为用户小部件。
假设我们有服务AUTH提供端点登录和注销,它还设置httpOnly
cookie。
这应该是标题,分布在webapps上。标题下载iframe并使用postMessage
向其发送调用,以了解用户是否已登录,否则显示登录:
<script>
/**
****************************************
* Code that should be inside the header
****************************************
*/
window.onload = function() {
(function(){
if (window.addEventListener) {
window.addEventListener("message", handleMessage, false);
} else {
window.attachEvent("onmessage", handleMessage);
}
//- This could be * meaning no preferences, or a URI,
//- but SHOULD not be * but the correct origin
var iframeOrigin = "*";
var iframeId = 'IFRAME-PROXY';
createIframe(checkStatusOfLogin);
var doLoginButton = document.getElementById('do-login');
doLoginButton.onclick = doLogin;
function createIframe(onLoadCallback) {
var iframe = document.createElement('iframe');
iframe.id = iframeId;
iframe.style.display = 'none';
iframe.src = 'https://mysecureiframe.securedomain.com/file.html';
document.body.appendChild(iframe);
iframe.onload = function () {
onLoadCallback(iframe);
};
}
function checkStatusOfLogin(iframe) {
var iframeWin = iframe.contentWindow;
var payload = {
action: 'status'
};
iframeWin.postMessage(JSON.stringify(payload), iframeOrigin);
}
function doLogin() {
var iframeWin = document.getElementById(iframeId).contentWindow;
var payload = {
action: 'login',
username: document.getElementById('username').value,
password: document.getElementById('password').value
};
iframeWin.postMessage(JSON.stringify(payload), iframeOrigin);
}
function handleMessage(evt) {
console.log('Inside client tab, received: ', evt);
var userContainer = document.getElementById('user-container');
try {
var parsedResponse = JSON.parse(evt.data);
if (parsedResponse.isCIA) { // checking it's a postmessage from us and not an extension
if (parsedResponse.status == "LOGGED_IN") {
userContainer.classList.remove('not-logged-in');
} else if (parsedResponse.status == 'NEED_LOGIN') {
userContainer.classList.add('not-logged-in');
}
} else {
throw new Error('not CIA message');
}
} catch (e) {
console.log('not CIA message');
}
}
}());
};
/**
*******************
* End of header code
* *****************
*/
</script>
iframe包含一个非常简单的正文:
<!DOCTYPE html>
<html>
<head>
<script src="https://mysecureiframe.securedomain.com/loginProvider.js" type="text/javascript" ></script>
</head>
<body>
<p>IFRAME NON VISIBILE</p>
</body>
</html>
以下是loginProvider.js
:
(function() {
if (window.addEventListener) {
window.addEventListener("message", handleMessage, false);
} else {
window.attachEvent("onmessage", handleMessage);
}
// to read: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
// Guardare HEADER Content-Security-Policy instead of X FRame Options
function checkStatus(success, failure) {
var http = new XMLHttpRequest();
var url = "https://mysecureiframe.securedomain.com/status"; // AUTH endpoint
http.open("GET", url, true);
http.onreadystatechange = function() { //Call a function when the state changes.
if (http.readyState == 4 && http.status == 200) {
if (http.responseText == "true") {
success();
} else {
failure();
}
}
};
http.send();
}
function doLoginIframe(user, pass) {
var http = new XMLHttpRequest();
var url = "https://mysecureiframe.securedomain.com/login"; // AUTH endpoint
http.open("POST", url, true);
http.onreadystatechange = function() { //Call a function when the state changes.
if (http.readyState == 4 && http.status == 200) {
if (user == 'username' && pass == 'password') {
var payload = getPayload();
payload.status = 'LOGGED_IN';
parent.postMessage(JSON.stringify(payload), "http://targetOrigin");
alert(http.responseText);
}
}
};
http.send();
}
function getPayload() {
return {
isCIA: true
};
}
function handleMessage(evt) {
console.log('Inside iframe, got: ', evt); // TODO Check targetOrigin is from trusted sites
var parsedRequest = JSON.parse(evt.data);
if (parsedRequest.action == "status") {
checkStatus(function() {
var payload = getPayload();
payload.status = 'LOGGED_IN';
parent.postMessage(JSON.stringify(payload), "http://targetOrigin");
},
function () {
var payload = getPayload();
payload.status = 'NEED_LOGIN';
parent.postMessage(JSON.stringify(payload), "http://targetOrigin");
});
} else if (parsedRequest.action == "login") {
doLoginIframe(parsedRequest.username, parsedRequest.password);
}
}
}());
除了添加检查以查看origin是否是受信任的站点之外,您是否看到使用此策略的特定安全流?