概念
- Single Sign On,单点登录,在多个应用系统中,只需要登陆一次,就可以访问其他相互信任的应用系统
- 比如说有4个系统,其中三个是业务系统,没有登录模块,还有一个是SSO系统,只有登录模块,没有其他的业务模块。当这三个业务系统需要登录时,就跳到SSO系统,SSO系统完成登录,其他应用系统也就随之登录了
单系统登录
- HTTP协议是无状态的,所以服务器无法确认用户的信息
- 为了解决这个问题,用户在登录之后,我们在这个用户的session中标记登录状态为已登陆,同时服务器会向用户浏览器发送一个cookie,cookie是这个用户的唯一标识
- 下次再访问这个应用的时候,请求中会带上这个cookie,服务端根据这个cookie找到对应的seesion,通过session来判断这个用户是否登录
同域下的单点登录
存在的问题
- cookie不能跨域。在SSO系统登录后的cookie的域是SSO系统,给其他系统发送请求时是带不上的
- session只存在于自己的系统内,只有SSO系统的session记录了该用户,其他应用无法共享该session
问题解决
- 在SSO登录之后,将cookie的域设为顶域,这样所有子域下的系统就都可以访问到该cookie
- 共享SSO系统和其他业务系统的session,解决方案如Spring-Session等
不同域下的单点登录
CAS: Central Authentication Service
访问app1的流程
- 用户访问app系统,该系统需要登录,但是该用户未登录
- 跳转到CAS server,也就是SSO登录系统。SSO系统也未登录,弹出登录页
- 用户填写用户名密码,SSO系统认证后,将登陆状态写入SSO的session,浏览器中写入SSO域下的cookie
- SSO系统登录完成后生成一个Service Ticket(ST),然后跳转到app系统,同时将ST作为参数传递给app系统
- app系统拿到ST后,从后台向SSO系统发送请求,验证ST是否有效
- 验证通过后,app系统将登录状态写入该系统的session并设置app域下的cookie
访问app2的流程
- 用户访问app2系统,app2系统没登陆,跳转到SSO系统
- SSO系统已登录,生成ST,跳转回app2,将ST作为参数传递给app2
- app2拿到ST,后台访问SSO,验证ST是否有效
- 验证成功后,app2将登录状态写入session,并在app2域下写入cookie
验证ST的原因
业务系统拿到ST后需要再次访问SSO进行验证,是为了防止直接在浏览器中敲入回调业务系统的地址,并带上伪造的用户信息。如果不再次访问SSO验证,这种情况下业务系统也会认为用户已登录
参考:https://www.jianshu.com/p/75edcc05acfd