单点登录

定义

单点登录(Single Sign-On,简称 SSO。是目前比较流行的企业业务整合的解决方案之一。

是指用户只需要登录一次,即可在多个应用系统中访问受授权的资源。其原理是在用户登录之后,服务器会颁发一个令牌(Token),并将该令牌保存在共享的存储中(例如 Redis、数据库等),然后在用户访问其他应用系统时,该系统会向认证服务器发送请求,如果该用户已经登录过,则认证服务器会颁发一个新的令牌,否则需要用户重新登录。

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

实现

方式1:通过session进行验证

session 称为"会话",session 对象存储特定用户会话所需的属性及配置信息。简言之,session 就是服务器为了储存用户信息而创建的一个验证手段。用户在登录了一个系统后,服务器会将登录信息储存在一个 session 中,产生 session ID,客户端会保存该 ID;当这个用户再登录其他系统时,服务器会自动复制上一个模块的 session 该服务器的 session 中,以获取用户登录信息,实现用户只登录一次,就可以登录其他系统。在用户退出登录时,服务器会自动删除 session。

整个过程均在服务器端完成,用户实际使用时没有感知。

方式2:通过cookie进行验证

cookie 是某些网站为了辨别用户身份,由服务端生成,发给客户端暂时或永久保存的信息。简言之,cookie 就是一种存储用户数据的媒介。举例来说,当我们打开一个网站,比如新浪、CSDN、知乎时,输入用户名和密码登录后系统会弹出是否保存 cookie,如果我们选择保存,在下一次登录时,就不需要再次输入用户名和密码,而是默认登录成功,直接进入页面。

方式3:通过token进行验证

token 在身份认证中是令牌的意思,在词法分析中是标记的意思。一般作为邀请、登录系统使用。简言之,token 就是一种凭证,用户在登录注册时需要获取凭证,在经过验证后,方可登录相关被授权的应用。

用户在首次登录系统时输入账号和密码,服务器会收到登录请求,然后验证是否正确;

服务器会根据用户信息,如用户 ID、用户名、秘钥、过期时间等信息生成一个 token 签名,然后发给用户;

用户验证成功后,返回 token;

前端服务器收到 token 后,存储到 cookie 或 Local Storage 里;当用户再次登录时,会被服务器验证 token;

服务器收到用户登录请求后,对 token 签名进行比对:如果 token 验证正确,用户登录成功;如果 token 验证不正确,用户登录失败,跳转到登录页。

区别

在 Authing 中,无需手动编写操作 session、cookie 或是 token,控制台中可以一键体验单点登录功能,并且支持自建与集成第三方等多种方式,还可以通过 SDK 接入并自定义自己的应用与登录方式。

同域名下的单点登录

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

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

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

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

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

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

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

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

  • 如果认证中心发现用户尚未登录,则返回登录页面,等待用户登录。
  • 如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标URL,并在跳转前生成一个token,拼接在目标URL的后面,回传给目标应用系统。

应用系统拿到token之后,还需要像认证中心确认下token的合法性,防止用户伪造。确认无误后,应用系统记录用户的登录状态,并将token写入cookie,然后给本次访问放行。(注意这个cookie是当前应用系统的)当用户再次访问当前应用系统时,就会自动带上这个token,应用此种实现方式相对复杂,支持跨域,扩展性好,是单点登录的标准做法。

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

可以将Session ID(或 Token)保存到浏览器的LocalStorage中,让前端在每次向后端发送请求时,主动将LocalStorage的数据传递给服务端。这些都是由前端来控制的,后端需要做的仅仅是在用户登录成功后,将Session ID(或 Token)放在响应体中传递给前端。

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

关键代码如下:

js 复制代码
// 获取token
let token = result.data.token;

// 动态创建一个不可见的iframe,在iframe中加载一个跨域HTML
let iframe = document.createElement("iframe")
iframe.src = "http://app1.com/local.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被多个域所共享。

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

可能会用到的算法

通过key获取当前浏览器地址URL上的value

js 复制代码
function getUrlValue(name) {
  let reg = new RegExp('(^|&)' + name + '=([^&]*)(&|$)')
  let r = window.location.search.substr(1).match(reg)
  if (r != null) return unescape(r[2])
  return null
}

eg:

js 复制代码
// url :https://www.baidu.com?a=1&b=2

getUrlValue(a)  // 1
getUrlValue(b)  // 2
相关推荐
Fan_web12 分钟前
jQuery——事件委托
开发语言·前端·javascript·css·jquery
安冬的码畜日常14 分钟前
【CSS in Depth 2 精译_044】第七章 响应式设计概述
前端·css·css3·html5·响应式设计·响应式
莹雨潇潇1 小时前
Docker 快速入门(Ubuntu版)
java·前端·docker·容器
严文文-Chris1 小时前
【设计模式-中介者模式】
设计模式·中介者模式
Jiaberrr1 小时前
Element UI教程:如何将Radio单选框的圆框改为方框
前端·javascript·vue.js·ui·elementui
刷帅耍帅1 小时前
设计模式-中介者模式
设计模式·中介者模式
刷帅耍帅2 小时前
设计模式-组合模式
设计模式·组合模式
Tiffany_Ho2 小时前
【TypeScript】知识点梳理(三)
前端·typescript
安冬的码畜日常3 小时前
【D3.js in Action 3 精译_029】3.5 给 D3 条形图加注图表标签(上)
开发语言·前端·javascript·信息可视化·数据可视化·d3.js
刷帅耍帅3 小时前
设计模式-命令模式
设计模式·命令模式