实现SSO单点登录

不同域名如何实现单点登录,如

天猫 www.tmall.com

淘宝 www.taobao.com

实现方式一:父域 Cookie

domain属性 必须a.test.com b.test.com

实现方式二:认证中心CAS

麻烦

实现方式三:LocalStorage 跨域

iframe + postMessage 来实现的。

必备知识点

  1. 你要知道什么是跨域。
  2. 你要知道不同的域名cookie和localStorage是不共享的。
  3. 现在登录一般都是后端给你返回你一个token,然后你每次请求都拿着这个token去请求接口,所以,如何实现当淘宝登录成功的时候,生成的token给到天猫的localStorage域中呢?
  4. 后台肯定是一个统一登录鉴权。

主要代码实现

test1系统主要实现

SSO单点登录


<!DOCTYPE html>
<html>
<head>
    <title>用户登录.html</title>

    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="js/ajax.js"></script>
</head>

<body>
<form name="user" action="LoginController.php" method="post">
    <table  align="center">
        <tr>
            <td>用户名</td>
            <td>
                <input type="text" value="admin" name="username" />
            </td>
        </tr>
        <tr>
            <td>密码</td>
            <td>
                <input type="password" value="123456" name="password"/>
            </td>
        </tr>
        <tr>
            <td></td>
            <td>
                <input type="button" onclick="login()" name="tijiao" value="登录"/>
            </td>
        </tr>
    </table>
</form>
<!-- 通过 iframe 嵌入子页面 -->
<iframe hidden src="http://test2.com/iframepage.html" id="otherPage" ></iframe>
<script>
    function login() {
        var data = {"username":"admin","password":"123456"}
        myAjax("POST",'LoginController.php',data,null,function (result) {
            if (result.status == 1){
                var token = result.token;
                localStorage.setItem("token",token);
                alert("登录成功");
                //主要代码:向test2.com系统发送token
                document.getElementById("otherPage").contentWindow
                    .postMessage(
                        token,
                        "http://test2.com/iframepage.html"
                    );
                location.href="home.php"
            }else{
                alert("登录失败");
            }
        })
    }
</script>
</body>
</html>

test2系统主要实现

SSO单点登录


<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>iframe+postMessage跨域通信 子页面</title>
</head>
<body>
<h2>test2子页面</h2>
<div>
    <h3>接收消息区域</h3>
    <span id="message"></span>
</div>
</body>
<script>
    //监听发送的数据
    window.addEventListener('message',function(event){
        console.log(event);
        document.getElementById('message').innerHTML = "收到"
            + event.origin + "消息:" + event.data;
        localStorage.setItem("token",event.data);
    }, false);
</script>

</html>

逻辑梳理

首先,系统a和系统b要想进去自己的home页面,必须要登录,当系统a登录成功之后,系统b则不需要登录就可以访问自己的home页面。反之亦然

就是当系统a在登录成功的时候,后台返回的token同时也放到了系统b的localStorage里面,所以当系统b请求home页面的时候,发现自己的localStorage里面有值并且是正确的,就可以访问

来源
如何实现SSO单点登录?

本作品采用《CC 协议》,转载必须注明作者和本文链接
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
讨论数量: 12

难点应该是【绝对】保证同步登出

1年前 评论
my38778570 (楼主) 1年前
cevin (作者) 1年前
随波逐流

SAML 可以了解下

1年前 评论

多年前搞过一套CAS

1年前 评论
my38778570 (楼主) 1年前
daimonhunter (作者) 1年前
陈先生

我们现在正在用的方案是 SAML, 我觉得可以了解一下。

1年前 评论
my38778570 (楼主) 1年前

在 IDaaS 中,难点不是 SSO,而是 SLO——单点登出,在实际的业务中,你的系统必须兼容 Token、Session 等认证方式。

你自己也提到了 Authing,结合他们的文档,可以学习一些基本概念和术语。

推荐一些开源项目给你:

我们目前在用的是 ZITADEL,我们主要是结合 API Gateway 实现后段微服务的统一认证,该项目也还在成长,我也有幸给这个项目提了 PR。

这是我的 Blog 《开源身份认证和授权解决方案》

1年前 评论

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!