基于node.js实现简单的单点登录功能

单点登录的简单介绍

登录应该说是很常见的功能了,用户输入账号和密码,通过验证之后就可以正常访问到自己想要的资源。但是在某一些场景,比如一个大型的应用被拆分成若干个小应用部署在若干机器上,并且每一个应用都有需要被保护的资源,那么为每个应用都定制一个登录功能就显得较为繁琐了,而且对用户而言,每一次访问一个应用都要去登录,肯定体验是非常差的。要是登录过一次,就可以在访问所有互相信任的应用的资源就好了。

关于session

web应用最常用的是HTTP协议,这个应用层协议的特点就是无状态,服务器是不知道若干个请求是否是同一个用户发出的。所以就有了session和cookie这么一说。在登录成功之后,服务器通过某种存储手段记下用户的基本信息,并且在cookie中种下一个关键的key,以后只要是通向这个域名的请求,都会带上这个cookie,而服务器利用这个cookie中的key值就可以找到用户的信息,判别他身份。

单点登录到底做了什么

登录之后,你的信息就被保存在服务端了,之后的访问由于能检测到你的session,从而都是合法的。如果你想在一个应用登录之后,去其他应用不用登录都能直接访问,那么就需要去拿到你的session信息,也就是说,不同应用之间可以共享你的会话信息

认证中心

认证中心用来保存一个全局会话,可以理解为用户在这里保存了个状态,相对的,用户在应用中的状态,就是局部会话。这里我实现的逻辑是,在认证中心或者某个应用登录之后,在另一方都能登录。相反,注销一个,另一个也自动注销。

梳理下流程

假如有俩个应用A和B,还有个认证中心CAS。那么逻辑应该是这样的:
基于node.js实现简单的单点登录功能
这里只画了访问A时的过程,可以看到,假如访问A时,检测到没有登录的话(也就是没有生成局部会话),那么就会检测是否含有令牌,如果有了令牌,那么就向认证中心获取用户信息,并且建立局部会话,其实从图中可以看出,如果有了令牌,说明此时已经建立过全局的会话信息。要是没有令牌,那么接下来就是重定向到CAS的登录页了,具体可以从上面的图中看出来。

同理,当访问B的时候,就是没有登录,并且没有令牌。但是由于A已经登录过了,所以存在全局会话,所以也不用再去手动输入账号密码了。

注销时发生什么

注销其实就是消除用户的session,这里的关键其实就是,当A注销的时候,不仅要消除局部的会话,还得通知认证中心把全局会话给消除了,并且认证中心要通知所有的相关应用去消除各自的局部会话。

几个场景

现在假如在认证中心和应用都没有访问过。那么:

  • 先访问A,此时需要登录,输入账号密码,最后返回资源,此时去认证中心也是直接访问,不用登录。当然另一个应用B来访问,也不用登录。
  • 先访问认证中心,输入账号和密码之后,相当于先在认证中心建立一个全局的会话。之后的应用来访问。也不用登录。
  • 用户已经登录过,然后在A应用点了注销,那么此时会重定向到登录页面,并且认证中心也要和其他已经登录的相关应用全都要注销。
    -用户在认证中心点了注销,其他相关应用也要全部注销

代码

代码是基于node.js实现的,只是实现了上述的流程,整理以后会贴出github地址,仅供参考。其实这里面还有很多细节的设计,并且涉及许多复杂的东西。