首页 > 其他分享 >keycloak~对接login-status-iframe页面判断用户状态变更

keycloak~对接login-status-iframe页面判断用户状态变更

时间:2023-12-25 14:33:05浏览次数:34  
标签:status origin cookie iframe var login 页面

上次我们说了,keycloak的login-status-iframe页面的作用,并解决了跨域情况下,iframe与主页面数据传递的方法,这一次,我们主要分析login-status-iframe.html这个文件的源码,然后分析在我们系统中如何与这个页面对接。

login-status-iframe.html源码

<script>
    var init;

    function checkState(clientId, origin, sessionState, callback) {
        var cookie = getCookie();

        var checkCookie = function() {
            if (clientId === init.clientId && origin === init.origin) {
                var c = cookie.split('/');
                if (sessionState === c[2]) {
                    callback('unchanged');
                } else {
                    callback('changed');
                }
            } else {
                callback('error');
            }
        }

        if (!init) {
            var req = new XMLHttpRequest();

            var url = location.href.split("?")[0] + "/init";
            url += "?client_id=" + encodeURIComponent(clientId);
            url += "&origin=" + encodeURIComponent(origin);

            req.open('GET', url, true);

            req.onreadystatechange = function () {
                if (req.readyState === 4) {
                    if (req.status === 204 || req.status === 1223) {
                        init = {
                            clientId: clientId,
                            origin: origin
                        }
                        if (!cookie) {
                            if (sessionState != '') {
                                callback('changed');
                            } else {
                                callback('unchanged');
                            }
                        } else {
                            checkCookie();
                        }
                    } else {
                        callback('error');
                    }
                }
            };

            req.send();
        } else  if (!cookie) {
            if (sessionState != '') {
                callback('changed');
            } else {
                callback('unchanged');
            }
        } else {
            checkCookie();
        }
    }

    function getCookie()
    {
        var cookie = getCookieByName('KEYCLOAK_SESSION');
        if (cookie === null) {
            return getCookieByName('KEYCLOAK_SESSION_LEGACY');
        }
        return cookie;
    }

    function getCookieByName(name)
    {
        name = name + '=';
        var ca = document.cookie.split(';');
        for(var i=0; i<ca.length; i++)
        {
            var c = ca[i].trim();
            if (c.indexOf(name)===0) return c.substring(name.length,c.length);
        }
        return null;
    }

    function receiveMessage(event)
    {
        if (typeof event.data !== 'string') {
            return
        }

        var origin = event.origin;
        var data = event.data.split(' ');
        if (data.length != 2) {
            return;
        }

        var clientId = data[0];
        var sessionState = data[1];

        checkState(clientId, event.origin, sessionState, function(result) {
            event.source.postMessage(result, origin);
        });
    }

    window.addEventListener("message", receiveMessage, false);
</script>

具体方法说明

这个页面主要由以下4个方法组成,下面分别去介绍

  1. checkState(clientId, origin, sessionState, callback) 检查当前浏览器上,用户在keycloak登录的状态
  2. getCookie() 获取cookie中存储的用户状态
  3. getCookieByName(name) 获取指定key的cookie值
  4. receiveMessage(event) 接收从父页面通过postMessage传过来的消息

getCookieByName方法

按着指定向名称,从浏览器的cookie中获取,这是所有可见cookie的字符串,每对使用分号分开,咱们这个方法是返回了某个key对应的具体value.

getCookie方法

获取KEYCLOAK_SESSION的值,如果它不存在,就获取KEYCLOAK_SESSION_LEGACY的值,之所以有KEYCLOAK_SESSION_LEGACY,主要是考虑到了浏览器的兼容性问题。

receiveMessage方法

这个方法主要是用来接收主页面发过来的数据,然后进行状态检查的,子页面通过window.addEventListener("message", receiveMessage, false);来进行事件监听,主页面会提供client_id和sesssion_state,并使用空格将两个参数分开,然后在回调方法里,会向主页面进行通知,通过event.source.postMessage(result, origin);实现,result表示通知的内容,origin表示主页面的域名,其实这是为了安全考虑的,在主页面收到消息后,也会判断这个origin,会判断是否从子页面的域名;所以这个origin其实是事件的发起者的域名。

checkState方法

这是整个login-status-iframe.html页面的核心方法,主要用来判断登录状态,下面分步骤说一下:

  1. 它首先会从浏览器cookie中拿出KEYCLOAK_SESSION的值,它和主页面传过来的值做对比,如果相同状态就没改变(可能已登录或者未登录),如果不相同,如果说明状态改变了;
  2. 判断init是否初始化,如果没有,就从login-status-iframe.html/init?client_id=...这个keycloak的接口中,异步获取登录状态写入浏览器cookie,然后再用步骤1做状态判断;
  3. 如果init已经完成初始化,就直接检查cookie中的用户状态

主页面对接login-status-iframe.html页面

<iframe src="https://kc.com/auth/realms/{you}/protocol/openid-connect/login-status-iframe.html"
                    id="keycloak-status-iframe" style="display:none"></iframe>
<script>
 function getQueryVariable(variable) {
      var query = window.location.search.substring(1);
      var vars = query.split("&");
      for (var i = 0; i < vars.length; i++) {
          var pair = vars[i].split("=");
          if (pair[0] == variable) {
              return pair[1];
          }
      }
      return (false);
  }

  var iframe = document.getElementById('keycloak-status-iframe');
  iframe.onload = function () {
      var val = "democlient ";
      if (getQueryVariable("code")!="" && getQueryVariable("code").split(".").length == 3) {
          val = "democlient " + getQueryVariable("code").split(".")[1];//这里向iframe传的参数是"client_id session_state"
      }
      iframe.contentWindow.postMessage(val, 'https://kc.com');
      window.addEventListener('message', function (event) {
          if (event.origin !== 'https://kc.com') {
              return;
          }
          if (event.data === 'unchanged') {
              alert('用户会话未发生变化');
          } else if (event.data === 'changed') {
              alert('用户会话状态发生变化,可能已经注销');
          }
      }, false);


  }
</script>

标签:status,origin,cookie,iframe,var,login,页面
From: https://www.cnblogs.com/lori/p/17925956.html

相关文章

  • Linux 启动MySQL 报错:Status:“Server shutdown complete“ Error:13(权限不够)
    Status:“Servershutdowncomplete”Error:13(权限不够)我在银河麒麟V10系统中安装启动MySQL出现的一个错误:“Servershutdowncomplete”Error:13(权限不够),我在其他系统中没有遇到到。问题背景在国产化系统银河麒麟V10上尝试启动MySQL服务器时,可能会收到如下错误信息:Status:"Ser......
  • keycloak~从login-status-iframe页面总结如何跨域传值
    login-status-iframe.html是keycloak为我们提供的一种检测用户登录状态的页面,它要求用户对接的系统通过iframe进行嵌入,然后通过window.addEventListener去订阅子页面的信息。提示:所有HTMLDOM事件,可以查看我们完整的https://www.runoob.com/jsref/dom-obj-event.html。addE......
  • sql server pre-login troubleshooting
    wireshark抓包之后,首先过滤数据库服务器的IPip.src==172.22.58.4orip.dst==172.22.58.4找到第一条TCP握手记录之后,右键选中,FollowTCPstream然后会自动标记筛选出,从握手到断开的所有packet数据包tcp.streameq56 UsingSQLServer’sSNITracetoTroubleshootNetwor......
  • subprocess.CalledProcessError: Command ‘[‘ninja‘, ‘-v‘]‘ returned non-zero
    一、原因pytorch版本大于1.5二、解决1、降低pytorch版本将pytorch版本降到1.5以下2、禁用ninjiapytorch默认使用ninjia作为backend,将其禁用。替换为以下代码setup(...,cmdclass={#'build_ext':BuildExtension,'build_ext':BuildExtensi......
  • iframe父子页面通信相互调用传递参数多个postMessage
    效果如何运行父页面代码<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><metaname="viewport"content="width=device-width,initial-scale=1.0"><title>Document</title>......
  • 【WinForm详细教程五】WinForm中的MenuStrip 、ContextMenuStrip 、ToolStrip、Status
    原文链接:https://blog.csdn.net/QH2107/article/details/1341922511.MenuStripMenuStrip作为一个容器可以包含多个菜单项。MenuStrip的重要属性包括:Name:菜单的名字Dock:菜单的停靠位置Items:菜单项的集合ToolStripMenuItemToolStripMenuItem是MenuStrip中的菜单项,可以有以下......
  • git status用法
    gitstatus命令用于查看当前Git仓库中文件的状态。它会列出已修改、已暂存、未跟踪等文件的状态信息。使用gitstatus命令可以帮助你了解当前工作目录中哪些文件已经被修改、哪些文件已经被提交到了本地仓库中、哪些文件还没有被Git管理等信息。常用的参数包括:-s或--......
  • hbase运行status时报错
    在尝试运行status时出现了org.apache.hadoop.hbase.ipc.ServerNotRunningYetException:Serverisnotrunningyet的报错 解决方法——1.停止hbase集群2.在配置文件hbase-site.xml文件中增加如下配置<property><name>hbase.wal.provider</name><value>filesyste......
  • CentOS7 无法执行systemctl status ntpd的原因及解决方法
    在CentOS7中,NTP的服务名为ntpd.service,如果出现Unitntpd.servicecouldnotbefound的错误,可能是由于NTP没有安装或未正确启动所致。你可以尝试以下步骤来解决此问题:首先,检查系统是否已经安装NTP。可以运行以下命令:rpm-qntp如果返回packagentpisnotinstall......
  • 解决git status报错问题,以及git init初始化不成功问题
    VbenAdmin安装依赖时husky安装失败请查看你的源码是否从github直接下载的,直接下载是没有.git文件夹的,而husky需要依赖git才能安装。此时需使用gitinit初始化项目,再尝试重新安装即可。 在你要做的项目的文件夹中,空白区域右击鼠标,属性-安全-完全控制权限给允许......