概述

其实WEB单点登录的原理挺简单的,抛开那些复杂的概念,简单来讲讲如何实现一个最基本的单点登录

首先需要有两个网站

例如:

A 和 B 在登录认证逻辑上(通常使用的是 session 技术)将登录验证数据单独存在第三方的存储结构中 例如 数据库或者内存缓存服务器 关于这方面技术请自行去寻找相关资料(后端接口也可以)

  1. 用户在登录A站点的时候,创建登录信息,并存起来 然后留出一个接口 可以将一个已经登录的标识传递给B站点页面上

  2. 用户在访问B的时候 javascript 从 B 页面上获取到 A 的登录标识

  3. 将这个标识发送到 B 的后端查询用户是否在 A 上具有登录信息,如果存在则登录确认,直接跳过 B 站点的登录逻辑

那么在整个过程中,其实最麻烦的是 2 ,因为 A 和 B 的域名不同,在浏览器段往往不允许跨域传递数据

解决方案

利用B页面上的iframe来从 B 站点页面跳转到A站点接口页面上,通过 window.name 进行跨域通信

具体实施

A:

<?php
//index.php 创建需要跨域的信息 
setCookie('key','跨域的cookie内容');


<?php
//sso.php 接口
echo '<script>';
echo 'window.name ='.$_COOKIE['key'];
echo '</script>';

B:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
    </head>
    <body>
    <script type="text/javascript">
    function domainData(url, fn)
    {
        var isFirst = true;
        var iframe = document.createElement('iframe');
        iframe.style.display = 'none';
        var loadfn = function(){
            if(isFirst){
                iframe.contentWindow.location = 'http://www.site-b.com/null.html';
                isFirst = false;
            } else {
                fn(iframe.contentWindow.name);
                iframe.contentWindow.document.write('');
                iframe.contentWindow.close();
                document.body.removeChild(iframe);
                iframe.src = '';
                iframe = null;
            }
        };
        iframe.src = url;
        if(iframe.attachEvent){
            iframe.attachEvent('onload', loadfn);
        } else {
            iframe.onload = loadfn;
        }

        document.body.appendChild(iframe);
    }
    </script>

    <script type="text/javascript">
    domainData('http://www.site-a.com/sso.php', function(data){
        alert(data);
    });
    </script>
    </body>
</html>

同时要注意代码当中的 http://www.site-b.com/null.html 要创建一个这样的空白页面 保证iframe的访问顺序是 B的null → A的sso.php 现在先访问A的 index.php 创建 cookie ,然后再访问B的页面就可以获取到cookie数据了,至于具体怎么实现后端逻辑,不在本文探讨之内

随着时代的进步,现在这种方法已经不太常用了,只用来兼容旧版本的浏览器环境 新版本的浏览器已经可以使用 window.postMessage() 方案解决了。本文只是作为一种互联网记录保留了下来