单点登录

我们用大楼,保安,请求进入者,小纸条,来访者登记表这个场景比喻,整理了cookie(https://my.oschina.net/u/3412738/blog/3053558)和session(https://my.oschina.net/u/3412738/blog/3056411)。假设我们现在遇到一张这样的情况,就是G集团很大,它有很多幢大楼,按照之前的方式,来访者进入#1号大楼要校验登记,进入#2号大楼也要校验登录...以此类推,它需要在每一幢大楼里面都校验,并且登记一次,这样手续很繁琐,而且效率很低。那有没有一种方法,让我只要校验登记一次,就可以在整个集团内的所有大楼里畅行无阻呢?这就涉及到单点登录了。

单点登录

英文Single Sign On, 简单来说,就是在一个多系统的环境中,用户在其中一个系统登录后,在进入其他系统的时候,不需要再次进行登录,而是直接拥有登陆状态。这种多系统,主要是为了合理利用资源,降低耦合度,把原系统拆分成多个子系统而成的。比如,淘宝和天猫,它们就实现了单点登录功能,用户在淘宝登录后,进入天猫页面,就直接有了登录态。

HTTP回顾

众所周知,HTTP是无状态的写一,这意味着服务端无法确认用户的信息,于是有了cookie。这样,用户在后续的请求中都带上session_id,从而让服务端识别当前会话,以及当前会话的用户。当然,除了session_id之外,还可以使用token来区分。也就是在登录时,生成一个token,这个token可以保存在数据库中或者缓存中,对应到用户信息(比如以token为key, uid为value),然后把token写入cookie,之后的每次请求都带上cookie,然后通过cookie中的token来获取用户信息。

当然,cookie中的一些敏感信息要注意加密,使用的时候,传到服务端去解密。

登录意味着写入,那么注销登录意味着删除,记住我 意味着关闭浏览器后,在一段时间内打开浏览器,仍然保持登录状态。

多系统登录的问题及解决方案

3.1 Session(登记表)不共享问题

A系统的session存在A系统中,B系统的session存在B系统中,不互相共享,这样就不能共用同一个session_id了。

有以下几种方案:

3.1.1 会话复制: 可以做成session集群,然后集群内部完全同步,这样集群内部每一个节点都拥有集群所有节点的数据。但是这样会影响集群的性能,不建议使用。类似于所有大楼都存所有大楼的登记表。

3.1.2 会话保持:可以根据IP做Hash映射的负载均衡,这样同一个IP会一直访问同一台服务器。这样有一个问题,就是对服务器的稳定性要求高,如果出现宕(dàng)机,会有一大部分请求无法命中,迁移到其他机器。类似于一个总的登记中心,有很多个窗口,每个窗口都有去所有大楼的班车,但是每个窗口只处理一部分访问请求。

3.1.3 会话共享: 将Session数据放到缓存中,如Redis,使用Redis模拟Session. 核心思想就是

3.1.3.1 让客户端访问同一个sessionId
3.1.3.2 让所有域名对应的服务器访问的Session的数据的位置必须一致

类似于全集团共用同一个登记中心,每个大楼都可以直接去读写这个登记中心的数据。

我们可以把登录功能单独抽取出来,做成一个SSO子系统。其他的子系统登录时,请求SSO进行登录,如果已经登录,则直接放行,如果没有登录,则执行登录,SSO系统生成一个session_id或者token, 存入Redis, 返回时将session_id或者token放入cookie中,以后其他系统访问时带上cookie,拦截器得到session_id/token,判断是否存在,是否过期,进而判断是否已登录。

3.2 Cookie(小纸条)跨域问题

我们知道,Cookie中通过Domain域和Path路径来控制Cookie的使用范围。当浏览器访问A网站/系统时,会把A网站/域名的Cookie带过去,访问B时,也只会把B的Cookie带过去,由于域名不同,不会把其他域的Cookie带过去。

分几种情况

3.2.1 属于同一个顶级域名下的多个子域名,可以在设置Cookie时,讲Domain设为顶级域名,这样在访问顶级域名下的任何子域名时,浏览器都会带上该Cookie的键值对,就能共用同一个Cookie了。

3.2.2 跨多个顶级域名。这种情况有点复杂。


3.2.2.1 由于站点A(www.A.com)不能读取到由站点P(www.P.com)创建的加密ticket,所以当用户访问A站点上需要登录才能访问的资源时,A站点会首先查看是否有A-ticket。 如果有且没有过期,则直接使用。

3.2.2.2 如果没有或者已过期,则证明用户没有在A站点登录过或者已经失效,不过并不保证用户没有在B站点登录,(重复一下,既然是单点登录,当然无论你在A,B任意一个站点登录过,另外一个站点都要可以访问),请求会被重定向到P站点的验证页面.

3.2.2.3 校验P站点的Cookie, 如果存在且没有过期,则直接重定向回站点A,同时将验证信息Session_id/P-ticket返回给站点A。

3.2.2.4 如果P站点没有Cookie或者已失效,则跳转到Login登录页面,输入登录信息,登录页面完成登录后,生成一个P站点的Session_id/P-ticket,写入一个加密cookie,然后重定向到A站点的登录处理页,并把加密的用户信息作为参数传递给这个页面,这个页面接收登录页的用户信息,解密后也要写一个cookie,也就是A-ticket,今后用户再次访问A站点上需要登录权限才能访问的资源时,只需要检查这个A-cookie是否存在就可以了。

3.2.2.5 当用户访问B站点时,会重复上面的过程,监测到没有B-ticket,就会重定向到P站点的验证页面,去检查P-ticket,如果没有,就登录,有则返回B的登录处理页面写B-ticket。

3.2.2.6 注销的时候需要删除P-ticket和A-ticket。

3.2.2.7 怎么删除cookie: 简单的说其实是创建一个和你要删除的cookie同名的cookie,并把cookie的expire设为当前时间之前的某个时间,不过在跨子域的删除cookie时有一点要注意:必须要把cookie的域设置为父域.

3.2.2.8 为了保证各个环节的传输的安全性,最好使用https连接。

到这里,我们已经可以实现单点登录了。

3.3 CAS原理

说到单点登录,就肯定会见到这个名词:CAS (Central Authentication Service),下面说说CAS是怎么搞的。

如果已经将登录单独抽取成系统出来,现在我们有两个系统,分别是www.java3y.com和www.java4y.com,还有一个SSO认证中心: www.sso.com

 

3.3.1 用户想要访问系统Awww.java3y.com受限的资源(比如说购物车功能,购物车功能需要登录后才能访问),系统Awww.java3y.com发现用户并没有登录,于是重定向到sso认证中心,并将自己的地址作为参数。请求的地址如下:

 www.sso.com?service=www.java3y.com

SSO认证中心发现用户未登录,将用户引导至登录页面,用户进行输入用户名和密码进行登录,用户与认证中心建立全局会话(生成一份Token,写到Cookie中,保存在浏览器上) 

认证中心重定向回系统A,并把Token携带过去给系统A,重定向的地址如下:

www.java3y.com?token=xxxxxxx

接着,系统A去SSO认证中心验证这个Token是否正确,如果正确,则系统A和用户建立局部会话(创建Session)。到此,系统A和用户已经是登录状态了。

3.3.2 此时,用户想要访问系统B www.java4y.com受限的资源(比如说订单功能,订单功能需要登录后才能访问),系统B www.java4y.com发现用户并没有登录,于是重定向到SSO认证中心,并将自己的地址作为参数。请求的地址如下:

www.sso.com?service=www.java4y.com

注意,因为之前用户与认证中心www.sso.com已经建立了全局会话(当时已经把Cookie保存到浏览器上了),所以这次系统B重定向到认证中心www.sso.com是可以带上Cookie的。

认证中心根据带过来的Cookie发现已经与用户建立了全局会话了,认证中心重定向回系统B,并把Token携带过去给系统B,重定向的地址如下:

www.java4y.com?token=xxxxxxx

接着,系统B去sso认证中心验证这个Token是否正确,如果正确,则系统B和用户建立局部会话(创建Session)。到此,系统B和用户已经是登录状态了。

看到这里,其实SSO认证中心就类似一个中转站

转载于:https://my.oschina.net/u/3412738/blog/3056734

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值