单点登录是要求多域名 下共用一套登录的逻辑和数据,这个时候肯定会出现跨域问题
刚开始解决这个问题的方法是 用window.open打开的新窗口进行等待用户登录操作,原窗口进行 ajax轮询服务端接口 判断用户是否已登录。单点登录 并且不影响原界面的逻辑是实现了,但是要ajax轮询请求。(还有一种方案就是 可以通过爬取 第三方登录页面的二维码进行登录,但是这种方案逻辑太过于繁琐,而且针对不同平台的登录 都要单独写逻辑,所以不适用)
在实现了功能后 跨平台、不影响原界面 的单点登录功能后,决定优化一下,假如用户一旦增大,服务器压力必然爆表,优化的内容肯定就是ajax轮询了。
既然两个域名两个网页,那么必然跨域,cookie等这些肯定是用不上的,设置 父子页面通讯也过于繁琐并且没有保障的感觉。 我注意到 w_obj = window.open 函数返回的是 新窗口的对象,可以控制窗口关闭和判断窗口是否已关闭,但是调用 w_obj .name 时却提示跨域,那么有没有什么其他类似w_obj.closed的字段 是没有被跨域限制的呢?
打印了 w_obj,经过多次尝试,终于找到了一个 类似 w_obj.closed的字段:w_obj.length,找到文档
length:设置或返回窗口中的框架数量
文档说的框架是指 iframe 的数量,那么理论逻辑就走通了。思路就是:窗口a点击登录,弹出窗口b,窗口a进行 定时判断 w_obj.length 的值,窗口b进行第三方登录操作,登录成功后跳转到指定带有多个iframe的页面,窗口a判断出w_obj.length的值发生变化,则进行 请求判断用户是否已登录,如果登录成功则关闭窗口b。
php:
echo "<style>
iframe {
display:none;
}
</style>
<iframe></iframe>
<iframe></iframe>
<iframe></iframe>
<iframe></iframe>
<iframe></iframe>
<iframe></iframe>
";
die;
js:
// 居中打开 500*500 的新窗口 用于第三方登录
var w_obj = window.open(this.url, "_blank", "scrollbars=yes,resizable=1,modal=false,alwaysRaised=yes,height=500,width=500,top="+(window.screen.availHeight/2-250)+",left="+(window.screen.availWidth/2-250));
console.log(w_obj)
console.log(w_obj.frames)
// console.log(w_obj.innerHeight)
// 定时回调
var interval = setInterval(is_login, 500)
// 判断是否登录
function is_login()
{
if (w_obj != null && w_obj.closed){
// 我的窗口被关闭!
interval = window.clearInterval(interval)
window.sso_logined_func({code:509, msg:'请重新登录'}, login_type)
} else{
// console.log(w_obj.innerHeight)
// console.log(w_obj.length)
// 平台给出登录成功的信号,则进行获取登录成功后的数据
if(w_obj.length == 6) {
console.log('登录成功')
var result;
Ajax.get(window.host_url + window.api_path ,
{
type: 'token',
},
function(result ){
if (result.code == 200 && result.content != null) {
w_obj.close();
interval = window.clearInterval(interval)
window.sso_logined_func(result, login_type)
} else {
w_obj.close();
interval = window.clearInterval(interval)
window.sso_logined_func({code:500, msg:'登录失败,请重新登录'}, login_type)
}
});
}
}
}