流行的跨域单点登录验证

流行的跨域单点登录验证

PluginsKers
2021-03-25 / 2 评论 / 154 阅读 / 正在检测是否收录...

瞅瞅

单点登录

和OAuth鉴权不一样,不一样!
简称SSO,还是比较主流的企业业务整合的解决方案之一了

SSO一般都需要一个独立的认证中心PassPort,子系统的登录均需要通过PassPort

当一个系统登录成功后,PassPort将会办法一个令牌给各个子系统,子系统可以拿着令牌获取各自的受保护的资源,为了减少频繁,认证,各个子系统被PassPort授权后,会建立一个Session,在一定时间内无需再次认证

假如有四个系统:

  1. Application1
  2. Application2
  3. Application3
  4. SSO

Application1Application2Application3需要登录时,将请求到SSO系统,SSO系统完成登录后,其他的应用系统也就随之登录了。

举个栗子

淘宝、天猫都属于阿里旗下,当用户登录淘宝后,再打开天猫,系统便自动帮用户登录了天猫,这种现象就属于单点登录

如何实现

同域名下的单点登录

Cookiedomain属性设置为当前域的父域,并且父域的cookie会被子域所共享。path属性默认为web应用的上下文路径

利用cookie的这个特点,没错,我们只需要将cookiedomain属性设置为父域的域名(主域名),同时将cookiepath属性设置为根路径,将Session ID(或Token)保存到父域中。这样所有的子域应用就都可以访问到这个cookie

不过这要求应用系统的域名需建立在一个共同的主域名之下,如tieba.baidu.commap.baidu.com,它们都建立在baidu.com这个主域名之下,那么它们就可以通过这种方式来实现单点登录

不同域名下的单点登录(一)

如果是不同域的情况下,cookie是不共享的,这里我们可以部署一个认证中心,用于专门处理登录请求的独立的 Web服务

用户统一在认证中心进行登录,登录成功后,认证中心记录用户的登录状态,并将token写入cookie(注意这个cookie是认证中心的,应用系统是访问不到的)

应用系统检查当前请求有没有Token,如果没有,说明用户在当前系统中尚未登录,那么就将页面跳转至认证中心

由于这个操作会将认证中心的cookie自动带过去,因此,认证中心能够根据cookie知道用户是否已经登录过了

如果认证中心发现用户尚未登录,则返回登录页面,等待用户登录

如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标URL,并在跳转前生成一个Token,拼接在目标URL的后面,回传给目标应用系统

应用系统拿到Token之后,还需要向认证中心确认下Token的合法性,防止用户伪造。确认无误后,应用系统记录用户的登录状态,并将 Token写入cookie,然后给本次访问放行。(注意这个cookie是当前应用系统的)当用户再次访问当前应用系统时,就会自动带上这个 Token,应用系统验证Token发现用户已登录,于是就不会有认证中心什么事了

此种实现方式相对复杂,支持跨域,扩展性好,是单点登录的标准做法

不同域名下的单点登录(二)

LocalStorage的数据传递给服务端

这些都是由前端来控制的,后端需要做的仅仅是在用户登录成功后,将Session ID(或Token)放在响应体中传递给前端

单点登录完全可以在前端实现。前端拿到Session ID(或Token)后,除了将它写入自己的LocalStorage中之外,还可以通过特殊手段将它写入多个其他域下的LocalStorage

关键代码如下:

// 获取 token
var token = result.data.token;
 
// 动态创建一个不可见的iframe,在iframe中加载一个跨域HTML
var iframe = document.createElement("iframe");
iframe.src = "http://app1.com/localstorage.html";
document.body.append(iframe);
// 使用postMessage()方法将token传递给iframe
setTimeout(function () {
    iframe.contentWindow.postMessage(token, "http://app1.com");
}, 4000);
setTimeout(function () {
    iframe.remove();
}, 6000);
 
// 在这个iframe所加载的HTML中绑定一个事件监听器,当事件被触发时,把接收到的token数据写入localStorage
window.addEventListener('message', function (event) {
    localStorage.setItem('token', event.data)
}, false);

前端通过iframe+postMessage()方式,将同一份Token写入到了多个域下的LocalStorage中,前端每次在向后端发送请求之前,都会主动从LocalStorage中读取Token并在请求中携带,这样就实现了同一份Token被多个域所共享

此种实现方式完全由前端控制,几乎不需要后端参与,同样支持跨域

12

评论 (2)

取消
  1. 头像
    歆宋
    Windows 10 · Google Chrome

    好高端的样子!冲~

    回复
  2. 头像
    PluginsKers 作者
    Windows 10 · Google Chrome

    其实就是一个验证,和Oauth很相似表情

    回复