单点登录设计实现(一)

什么是单点登录?

先来看看最初的应用架构:

单点登录设计实现(一)

  经典的单体架构,服务中包含了三个模块,部署在一个服务器中。用户与服务端建立会话的方式是利用cookeis和session(见第二章节cookies和session)。但是随着系统内的业务越来越多,单个服务器已经不能满足性能要求,并且业务之间的交互越来愈多,业务耦合性很高,维护起来很麻烦,于是就把按每个业务单独分开来,形成一个子系统,用户需要每个系统的业务,就去对应的子系统访问,如下图:

单点登录设计实现(一)

用户需要对应的业务需求就去对应的子系统请求。当然这里的系统只是简单的拆分,各自系统之间的交互,系统的管理和治理这里都不讲,涉及到微服务的东西,以后再学习。这里讲单点登录足够了。用户在系统1登录之后,再去系统2、3……n都不需要登录了。举个例子,拿淘宝和天猫来说,如果你在淘宝的页面登录了,然后打开天猫的页面,你会发现你再天猫已经登录,并不用再天猫再登录一次,包括支付宝也是一样。

所谓的单点登录,功能可以简单的看做,有相关联子系统(比如天猫、淘宝、支付宝都是不同的系统),在其中一个登录之后,在进入其他子系统的时候,并不需要重新登录。这里的关键点在于,我在系统1登录之后,于系统1建立了联系,那么我怎么通知系统2,3……n,让他们知道我在系统1登陆了,到你们这里也就不用登陆了。

单点登录设计实现(一)

类似于上图这个意思,我们的重点在于解决第⑥⑦步的问题,该怎么设计实现。

所以这一次,我们就从头一步一步就来看看,单点登录是怎么设计的。

从系统登录说起:

      系统的登录想必大家都不陌生,用户在登陆界面登录,后台接受用户名和密码后,验证正确性,用户方可进入系统各页面。用户和服务端建立会话,此后的一段时间内,用户都不需要重新输入用户名密码,访问服务。

     注意这里的“会话”,这表示和服务端建立了联系,每次请求服务端都知道这个请求是你发过来的。但是我们都知道,http的请求是无状态的,每次建立连接都要三次握手,服务端并不能判断哪个http是你发送的,那么这里的会话是如何建立起来的,让服务端可以识别你呢? 这就要提到cookies和session了。

cookeis用于服务端返回给客户端的用户相关信息,在用户登录成功后,服务端会返回给浏览器端一些用户的信息,然后存放与浏览器端,每次浏览器发起请求时都会携带上cookies信息

session时用户首次登录后,服务端用于记录每个用户信息的东西,存放于服务端,每次请求过来之后,根据cookies中的信息,查找对应的session,进而找到session中的session信息。

而cookies和session交互的方式就是jessionID,具体交互方式如下:

   用户首次访问页面(登录成功)服务器(如tomcat)会为这个客户端随机生成一串字符串,即jessionID,并开辟一个空间存放用户的信息,如登录时间,用户角色等,所以在服务端的session存放的方式类似于map,key值就是jessionID,value值相当于session:

     单点登录设计实现(一)

 

如上图所示,每个user相当于一个浏览器,服务端的session就类似于存放了这样的结构。然后客户端会把jsessionID和浏览器需要知道用户信息放进cookies中,返回给浏览器。

 此后浏览器每次访问服务端,都会携带上cookies,自然也就携带了sessionID,服务端在收到请求之后,会判断有没有jseesionId:

如果没有,那说明用户是第一次访问(也有可能是存放在客户端的session过期了,session是有效期的,过期就需要重新登录进行获取),那么需要跳转到登录页面进行登录。

 如果存在,那服务端会拿到jessionID,和上面的这张表进行匹配,匹配到之后说明用户已经登录,然后进而获取用户的信息,比如user1 information,获得用户权限之类的信息,然后进而对请求做出响应。整体流程图如下:

单点登录设计实现(一)

其实你会发现,在进行开发的时候,我们并没有对jseesionId进行进行校验和检查之类的代码编写,这是因为这一步(包括创建session,创建JsessionID,jsessionID的校验)是tomcat(如果你的服务器用的是tomcat)自动为我们做了。而我们要做的就是在用户登录后在cookeis中设置浏览器所需要的的用户信息,和用户请求,根据jessionID获取session,获取或设置session中的用户信息进行响应,这里cookies和session中存放的数据,由业务而定。

需要注意的是,这里的cookies和session是有效期的。

对于session来说,有效期可以在服务端程序中设置,也可以在tomcat的配置文件中设置。超过设置的失效时间后,在接受客户端的请求时,就可以让其重新登录。达到登录时间的控制。如果用户在有效期请求,每次请求都会刷新session的有效期,从新计算,从而维持登录状态。只有用常识不发起请求,到了失效时间才会把对应session删除,用户再次请求时需要重新获取(重新登录)

对于cookeis来说可以在浏览器端设置cookies的属性,其中就包括了session的失效时间(具体属性可以百度)。如果不设置cookies的失效时间,则默认和session失效时间一致,因为session失效了,那么相对来说cookies也没用了。

为了更方便的了解,下面来实际看一看一个简单的测试:这里搭建了一个空工程,就访问index.jsp页面,当我们第一次访问网站的时候,在浏览器开发这工具中(F12进入),找到network中的heaaders:

单点登录设计实现(一)

正如我们上面说的那样,由于是第一次请求,在请求头部Request Headers中并没有携带cookies进行请求,反而是客户端在监测第一次登陆没有发现在cookies中jessionID的时候,生成了一个cookies,返回给浏览器,在ResponseHeaders中可以看到Set-Cookies里面就有生成的一个jessionID(红线所示)。然后浏览器会存放在本地,下次请求的时候机会携带上cookeis。接下来我们刷新一下页面,再发一次请求:

单点登录设计实现(一)

正如我们所想的那样,在请求头Request Headers中携带了Cookies,并且里面有JessionID。对比一下就会发现这个jsession就是第一次请求时服务端返回的jessionID。说明浏览器的确存储了服务端返回的cookies,并在下一次请求的时候携带上了,以供服务端进行校验。

      好啦,这次的cookeis和sesson就讲到这里啦,至于cookeis和session在tomcat和浏览器内部是如何实现的,然后还有他们的属性设置等深入的内网这里就不说了,感兴趣的小伙伴可以自行百度或者看看相关官方文档。

ps:文章只讲了cookies和sesion的基本原理,关于深入的实现、用法及api大家可以自行百度或看官方文档,重要的是思想,不是吗?(其实是我自己觉得贴出来很麻烦,我也要去搜,我也记不住,原谅我刚开始写文章就开始偷懒了,哈哈哈)