俗话说单点登录(SSO)的三种实现原理

1、什么是单点登录?

我们现在有千度和万度两个web服务

比如我们在一个浏览器登录了千度,接着再去访问万度,在访问万度的时候是不需要再次登录就可以直接访问的,这就是单点登录。

那么怎样才能达到这个目的呢?我这里给基于三种原理的实现方式。

2、三种原理

1、第一种实现原理

让浏览器记住千度的session,访问万度也用这个session。

让服务器记住千度的session,万度的登录认证也用这个session去认证。

相当于只有一把钥匙(session)开一把锁,获得钥匙的方式就是第一次用户名密码认证通过。

基于这种原理,我们从前端到后端来讲一下怎样保证拿到同一把钥匙开同一把锁。

拿同一把钥匙:千度和万度的使用相同的cookie域。

开同一把锁:方式1 千度和万度共用同一redis库管理session 方式2 tomcat共享session,把千度的session传输给万度。

我们看到这种方式是存在依赖和限制的,这可能是我们不能容忍的,比如百度视频和百度贴吧,并不会使用相同的域名。拿不到同一把钥匙,就会出现跨域问题:

当然我们可以使用jsonp或页面重定向的方式去解决跨域问题,这两种方式实现方式不一样但原理是一样的,于是在这里抛出基于第二种原理来实现的方式。

我先场景化一下:

你要进一个门,通过用户名密码拿到了这个门的钥匙(session),之后你要进另一个门,这个时候不需要去输第二个门的用户名密码拿钥匙,你直接从书包(cookie)里面拿出第一个门的钥匙去第一个门以这个钥匙为凭证拿到一张证明(token),证明你进过第一个门所以也有资格进第二个门,拿到证明后去第二个门出示这张有效的证明就可以拿到第二个门的钥匙进入。

2、第二种实现原理

如上所述,实现方式有两种,统称为分发的方式。图示

个人觉得jsonp/页面重定向的方式扩展性没有那么好。实际项目中往往需要一种更灵活解耦的方式,于是在这里抛出基于第三种原理来实现的方式。

我先场景化一下:

你要进一个门,第一次得先找阿姨输用户密码证明你是你,阿姨证明你是合法公民于是给你颁发了一个良民证和一个门卡,良民证你放进了书包里,你拿着门卡去门口的机器上刷一下,机器检测到你这个门卡确实是阿姨给你的门卡不是伪造的,于是机器吐了一把这个门的钥匙(session)给你开门进去。之后第二次第三次…再进这个门只要拿着这把钥匙进去就可以了。

这个时候如果你要进另一个门怎么办?你只要拿着书包里的良民证去阿姨那里领一张另一个门的门卡,并拿着这个门卡去另一个门的机器上刷一下,机器检测到你这个门卡不是伪造的,于是吐了一把钥匙给你开门进去,之后若要再进这个门,只需要拿出这个门的钥匙…

看起来是不是挺麻烦?但其实用户是完全感知不到的。

根据上面的比方,我们抓取关键的点。良民证(TGC)放在书包(Cookie),用良民证换门卡(Ticket),刷门卡时机器去检验这个门卡是不是那个阿姨给(web客户端隐式校验Ticket)的。

我们用术语翻译一下整个过程,也就是要介绍的基于第二种原理来实现的单点登录的方式。

3、第三种实现原理

第一次访问千度时检测到没有已登录的httpSession(钥匙),于是跳转到认证中心(阿姨)去登录(输用户名密码),认证中心登录成功后给浏览器Cookie种下TGC(良民证放书包)和颁发Ticket(门卡),并跳转到千度(带着门卡去门口刷),千度用拿着这个Ticket通过http的方式去认证中心认证Ticket是不是这个认证中心颁发的,Ticket认证通过,则标记当前httpSession为已登录的session(吐一把钥匙)。之后再访问千度的其它请求都会带上这个session一路绿灯。这时如果我去访问万度,万度发现没有登录成功的httpSession,于是重定向到认证中心,这次重定向会带上Cookie里的TGC,认证中心一看是带着TGC过来的,于是拿着TGC去校验是不是自己颁发的,发现是,则不用再输入用户名密码直接跳转回万度并带上新生成的Ticket,万度拿着Ticket再次跟认证中心匹配看是不是这个认证中心颁发的,发现是,记录当前session为已登录的session,之后再访问万度的其它请求都会带上这个session一路绿灯。图示

通过这种方式实现单点登录不受跨域限制,也不需要共享session。

猜你喜欢

转载自blog.csdn.net/nowitzkis/article/details/107338528