网页登录以及单点登录的一些概念

来源:互联网 发布:娶网络女主播 编辑:程序博客网 时间:2024/05/20 00:13

开发web应用,不免要涉及到登录以及权限等问题,独立的站点里,这些也不存在太大的问题,反正教程、代码很多的,但是在照抄代码的时候,应该还要考虑一下别人为什么要这样写,以后才能自己写,才能根据不同的需求设计不同的系统。而已经讨论的非常多的单点登录,相对就要复杂多了,看了好多次,看的时候好像看懂了,过后一想好像什么都不知道,具体设计的时候,必须要实现哪些对象,每个对象是用来干什么的,又是一头却雾水。最近又重新在网上看了一下单点登录的原理,目前的体会是:基础很重要,也就是说,要想掌握多站点的单点登录,先得熟悉单个站点的登录。

先来回顾一下,单个站点登录及用户权限的基本过程。大概画了个图,其中涉及到几个概念需要澄清一下,网上都说,用户登录成功后,登录信息保存在会话里?会话在哪里?网页编程,经常用到request、response、Server、Application、Session以及cookise这些对象以及生存周期,前面几个从名字上来说,意义还是比较清楚的,就是session的概念有些模糊,百度百科上是这样说的:Session 对象存储特定用户会话所需的属性及配置信息。这样,当用户在应用程序的 Web 页之间跳转时,存储在 Session 对象中的变量将不会丢失,而是在整个用户会话中一直存在下去。更懵的是,百度百科下面还有一个定义:在计算机专业术语中,Session是指一个终端用户与交互系统进行通信的时间间隔,通常指从注册进入系统到注销退出系统之间所经过的时间。以及如果需要的话,可能还有一定的操作空间。其实很多书上描述的也差不多,然后接下来就是session有哪些方法可用,如何用,然后就是上代码……,的确,概念清不清楚不要紧,反正照葫芦画瓢,程序照样能运行,功能照样实现。存在的问题是,一个概念理解不清,后面的概念就更难理解,甚至会理解错,越往后就越难,就越不清楚了。比如说,我就一直以为session是在浏览器和服务器之间来回传送的尴尬,因为可以从httpservletrequest里面getsession啊,而request不是客户端发送来的请求么。而我又经常把下拉选择框、列表框的内容保存在seession里面,然后经常想,如果网站复杂了,列表框多了,这些东西传来传去多浪费流量啊惊恐。好吧,浪费流量那是用户的事,但是现在讨论的登录问题,用户名、密码是不是也是在浏览器和客户端之间传来传去的呢?显然不可能啊,太不安全了。所以,决不是这样的,session只会保存在服务器端。反过来,如果session会传到客户端,那么javascript可以访问里面的内容喽,但是从来没有哪个javascript脚本教程这样用过啊。从这个角度,同样也说明了我以前的理解是错误的,好了,这下可以放心地往session里面放东西了,最多是多占点服务器内存而已大笑。但是,别急,但是如果session不传给客户端,那么客户端如何知道自己是处于哪一个session中,或者说服务器如何判断哪一个客户端是哪一个会话的?一定还是有些什么在客户端和服务器端传来传去的吧,肯定是有的,那就是session_id,不同的服务器,变量名不一样,但是道理都一样,这个就是个key或者说一个内存指针,反正服务器根据这个ID,就可以在服务器内存当中找到对应的Session对象来,也就是说API里面Httpservletrequest.getsession实际上就是根据客户端请求里面的sessionid查找到服务器端的session,然后就可以访问里面的内容了,并不是从request里面取出session的。浏览器访问服务器的时候,如果有这个ID就会把它跟随request一起发给服务器,这个变量多半是保存在内存或cookies里,cookies是存在客户端并且每次都发给服务器是肯定的,不管哪里吧,反正这事浏览器负责干,只要找得到,它都会发给服务器。然后服务器也并不是就认客户端发来的这个,最起码,客户端发来的ID它要能根据这个ID找得到对应的对象啊。找不到它就会重新申请一段内存,然后再把ID发给客户端,而客户端呢,就会记着这个新的ID,下次就用这个ID了。关于session大概就是这么回事了吧,已经偏离主题太远了。

接着讲用户的登录信息,用户的信息除了用户名、密码之外,一般还有一个角色,甚至权限列表,同样,这些信息如果在客户端和服务器之间传来传去的话,同样是一种资源浪费,并且,不安全。实际上,传来传去的只是一个token,token的作用其实和sessionID是一样的,跟用户名、密码没什么关系,也不需要有关系,就是一个key或者一个指针反正服务器端能根据这个token找出保存在session里面的用户信息来,这就够了。另外,刚才说的Session是由容器管理的,而token通常是由应用程序管理的,也就是说前面图中关于session的id以及创建session的过程,一般开发人员根本不用去考虑,只需要知道有这么个东西可以用就行了。这也就是为什么网上也好,书上也好,大都没讲得很透的原因吧。token就是用应用程序管理的,只不过,不管什么平台、什么框架,用户身份验证过程、发放token等都是包装好了的,只要按平台框架的要求写代码,能用是没问题的。但是要理解单点登录,这个底层的概念必须要理解清除了,才好理解上层为什么这么做。

很明显,要实现单点登录,用户名密码肯定是统一的,但是其他,比如权限,肯定各个系统还是各个系统的,各个系统肯定还是要按各自的办法保存用户的信息,包括会话里面已经登录的用户的信息,这个是没办法统一的,单点登录涉及到的各个软件,可能是不同的框架、语言、使用不同的容器和不同的操作系统,也完全没有可能全部统一。所以,做单点登录,基本上不会、也不可能改变原有系统或者要求所有子系统都要用同一种操作系统、应用服务器、程序语言、开发框架的,当然,最基本的要求或者对原有系统轻微的改造也是必须的。

好了,继续讲单点登录,其实对于单点登录中的各个子站点来说,实际上只有一点点不同,就是以前是自己用页面接收用户名密码自己验证,现在是交给一个统一的认证中心去认证,只要认证中心认证通过了,照样在session中保存用户信息,照样发token,这样session中的信息是自己从数据库里面取出来的,token是自己发的,以后的事情,还照样,根据token查找用户权限,根据用户权限不同发给客户端不同的东西,没什么变化。很简单,现在的问题在于其他站点,用户如果又要访问其他站点怎么办,还是这样要求用户发来用户名、密码,然后交给认证中心去认证肯定不行,那就不叫单点登录了,仍然和各登各的差不多,只不过是用户名、密码相同的罢了。并且,已经登录的系统也不可能把token发给其他子系统,就连认证中心也不能这样,一个是不知道用户什么时候用什么系统,用户没有访问其他系统的时候,那些系统里面连session都没有,用户信息保存在哪儿,token和什么对应,再说前面也说了,token就相当于一个内存指针,离开服务器就是一串二进制数,另外,即便有用,那所有系统之间要互相通迅,还要考虑系统之间信任的问题,得多麻烦啊。还有,退出又怎么办?所以问题还得靠认证中心解决。其实搞清楚单点登录的的原理后,也不算复杂,就是要利用用户已经在认证中心登录,利用用户已经和认证中心建立了会话,并且已经有认证中心的token,至于这个系统那个系统还有认证中心,用户的请求被后台重定向从这里跳转那里,又从那里跳转到这里,这背后的事情,客户不用参与也感觉不到的。好了,上图:

这图有点大哈,抄别人的,但又不是完全照搬,想尽量表达清楚些,就画得大了些。单点登的过程大概是下面这样的:

1.用户访问server1上的受限制的资源,结果server1发现该用户没有token也就是没有登录,普通的站点呢这时候一般是直接重定向或跳转到登录页,单点登录系统的话,就是重定向到sso认证中心去(图里面用redirect好像刚好用错了,反正上图里面redirect就是重定向,也就是响应一个地址给浏览器,让浏览器去访问该地址);

2.然后浏览器就去访问sso认证中心,结果sso发现该用户没有全局token也就是没有在中心登录过,这时候sso就直接响应登录页了(因为不可能再委托别人了);

3.用户输入用户名密码在sso中心登录,如果登录成功,sso自然是要发一个token给他的,这叫全局token,表示这个用户可以正常访问sso了,然后再生成一个临时的token给他,并且,叫他用这个token去访问刚才想访问的server1,这个地址是刚才用户第一次访问sso时带过来的,sso保存在session里的;

4.用户拿着这个临时的token去访问server1,server1一看拿着个token来的,当然不是马上就放行,而是拿这个token去sso验证,sso验证无误的话,就会记录下来,刚才那个用户申请的token是用于访问server1了,并且把这个用户的username发给server1。

5.server1收到sso确认的信息后,根据username把用户的权限之类的相关信息找到,放到session里面,然后响应用户请求的资源,并生成一个自己的token给用户(token不能用sso生成的那个,只能各自用各自的,前面已经说过了)。再往后,用户有了server1上的token之后,访问server1的其他资源就没什么问题了,和成功登录单个站点一样的,没什么区别;

6.然后,用户又想访问server2了,第一次请求server2时,同样的,由于并没有server2发的token,server2仍然会重定向用户到sso去;

7.用户又去访问sso,不过这次不太一样的是,他已经登录过sso了,有了sso发的全局token,所以这次访问sso的时候带上了全局token;

8.这回sso一看,有token的,又是想去访问哪个网站了,就又生成一个临时token给他;

9.用户拿着这个临时的token去访问server2,一样的,server2也要去验证,然后……重复。用户登录过sso后访问server2时,被重定向了两次,但是,无论server2还是sso都没有再response什么,用户根本就感觉不到页面有什么变化,直接就可以使用了。再访问其他站点也是一样,整个过程只需登录一次,这就是单点登录!

解释一点里面几个问题:

1.为什么sso要发临时token?为什么不是sso验证通过用户之后,就直接让子服务器通过对用户的验证?这是因为用户登录sso的过程是用户自己登录的,并不是子服务器server1或server2代替用户去的,所以sso验证通过用户之后不知道通知哪一个服务器,就算知道,http是无状态的嘛,还不知道用户有没有在用呢,就算有会话,是哪一个会话呢?整 个内存中搜索吗?所以sso不是这样设计的。另外,如果由服务器代理用户去登录的话,那好像不需要什么验证中心了,用户想访问哪个服务器,就代理去哪个服务器登录就完了嘛,而且这样也不行,用户并没有取得对应服务器上的token啊,就算代理把取得的token给用户也不行,因为,用户拿着这个token去访问的话,不是同一个会话啊,没用的。除非,除非这个服务器就老老实实地做代理,用户要访问哪个服务器,它就去登录哪个服务器,用户要访问什么它就访问什么,并且把取得的东西原样发给用户。这样也是可以的,不过这叫代理服务而不叫单点登录了。

2.sso为什么要登记用户登录了哪个服务器?这个是为了后面的注销。很明显,全局token的有效期应该是很长的,要不然用户在其中一个站点上用得好好的,有可能访问其他站点时又会要求重新登录。那么全局token的有效期多长才合适呢?要是用户刻意保存了这个token呢,那是不是可能关掉浏览器甚至关机了重新开机,只要恢复了这个token那么就可以再次访问所有系统(这里指的恶意)。所以,从安全角度考虑,有登录就要有注销,注销当然不能注销一个全部都注销,所以sso得记录下用户登录了哪些系统,用户注销一个就删除一个,所有系统都注销完了全局token就跟着注销。

注销这个环节还没有理解透,这里应该有一个机制,就是sso记录的用户访问各个子站点的信息有效期应该很短,但是活动着的那一个应该只要活动着就一直有效,这样用户单点登录后访问多个站点,但是,只要一小段时间不使用,sso上记录的信息就过时,但是没关系,只要有一个是有效的,全局token就还在,由于单点登录本身的特性,用户再访问其他站点也不会有要求重新登录的问题,但是用户一直在访问的使用着的那个站点在sso上的记录一定不能删,否则的话再访问就要重登录,就不是单点登录了。单点登录并不是说要单点一次性全部登录吧。反正每个站点实际上每次接受用户请求,都要验证用户的,我猜是不是在这个时候子站点会每次都向sso发数据,刷新信息的。这个只是猜了,估计不同的实现方案就会有不同的方法的吧。前几天看这方面资料,有人说用户注销,sso会通知其他服务器,这个我就不敢苟同了,通知其他服务器,连接在哪里,会话在哪里,就算通知了,服务器又怎么知道去注销哪个会话呢?http真的是无状态的啊。

原创粉丝点击