什么是单点登录?
单点登录(Single Sign On,简称SSO)
背景:
以前的时候,一般我们就单系统,所有的功能都在同一个系统上。
后来,我们为了合理利用资源和降低耦合性,于是把单系统拆分成多个子系统。比如阿里系的淘宝和天猫,很明显地我们可以知道这是两个系统,但是你在使用的时候,登录了天猫,淘宝也会自动登录。
如图所示,图中有4个系统,分别是Application1、Application2、Application3、和SSO。Application1、Application2、Application3没有登录模块,而SSO只有登录模块,没有其他的业务模块,当Application1、Application2、Application3需要登录时,将跳到SSO系统,SSO系统完成登录,其他的应用系统也就随之登录了。这完全符合我们对单点登录(SSO)的定义。
简单来说,单点登录就是在多个系统中,用户只需一次登录,各个系统即可感知该用户已经登录。
单点登录的来源:
1、早期web单系统应用:
早期web单系统应用,用户的登录以及权限就显得十分简单,当浏览器向服务器发送登录请求时,验证通过之后,会将用户信息存入seesion中,然后服务器会生成一个sessionId放入cookie中,随后返回给浏览器。
验证登录的这个会话就是session,维护了用户状态,也就是所谓的HTTP有状态协议,我们经常可以在浏览器中看到JSESSIONID,这个就是用来维持这个关系的key。
2、分布式集群部署:
由于网站的访问量越来也大,单机部署已经是巨大瓶颈,所以才有了后来的分布式集群部署。如果引入集群的概念,单应用可能重新部署在3台tomcat以上服务器,使用nginx来实现反向代理。
但是增加新的服务器之后,不同的服务器之间的sessionId是不一样的,可能在A服务器上已经登录成功了,能从服务器的session中获取用户信息,但是在B服务器上却查不到session信息,只好退出来继续登录,结果A服务器中的session因为超时失效,登录之后又被强制退出来要求重新登录。
所以不得不考虑多服务器之间的session数据一致的问题,这就是单点登录的最早来源。
单点登录技术实现:
单点登录的本质就是在多个应用系统中共享登录状态,如果用户的登录状态是记录在 Session 中的,要实现共享登录状态,就要先共享 Session。
所以实现单点登录的关键在于,如何让 Session ID(或 Token)在多个域中共享。
1、同域下的单点登录:
一个企业一般情况下只有一个域名,通过二级域名区分不同的系统。比如我们有个域名叫做:a.com,同时有两个业务系统分别为:app1.a.com和app2.a.com。我们要做单点登录(SSO),需要一个登录系统,叫做:sso.a.com。
实现方式:
在sso.a.com中登录了,其实是在sso.a.com的服务端的session中记录了登录状态,同时在浏览器端(Browser)的sso.a.com下写入了Cookie。那么我们怎么才能让app1.a.com和app2.a.com登录呢?这里有两个问题:
Cookie是不能跨域的,我们Cookie的domain属性是sso.a.com,在给app1.a.com和app2.a.com发送请求是带不上的。
sso、app1和app2是不同的应用,它们的session存在自己的应用内,是不共享的。
那么我们如何解决这两个问题呢?
sso登录以后,可以将Cookie的 domian 域设置为顶域,即.a.com,这样所有子域的系统都可以访问到顶域的Cookie。在设置Cookie时,只能设置顶域和自己的域,不能设置其他的域。
把3个系统的Session共享,共享Session的解决方案有很多,例如:Spring-Session
2、跨域下的单点登录
如果是不同域呢?不同域之间Cookie是不共享的,怎么办?
这里我们就要说一说CAS流程了,这个流程是单点登录的标准流程。
具体流程如下:
1)用户访问app系统,app系统是需要登录的,但用户现在没有登录。
2)跳转到CAS server,即SSO登录系统,以后图中的CAS Server我们统一叫做SSO系统。 SSO系统也没有登录,弹出用户登录页。
3)用户填写用户名、密码,SSO系统进行认证后,将登录状态写入SSO的session,浏览器(Browser)中写入SSO域下的Cookie。
4)SSO系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
5)app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。
6)验证通过后,app系统将登录状态写入session并设置app域下的Cookie。
至此,跨域单点登录就完成了。以后我们再访问app系统时,app就是登录的。接下来,我们再看看访问app2系统时的流程。
1)用户访问app2系统,app2系统没有登录,跳转到SSO。
2)由于SSO已经登录了,不需要重新登录认证。
3)SSO生成ST,浏览器跳转到app2系统,并将ST作为参数传递给app2。
4)app2拿到ST,后台访问SSO,验证ST是否有效。
5)验证成功后,app2将登录状态写入session,并在app2域下写入Cookie。
这样,app2系统不需要走登录流程,就已经是登录了。SSO,app和app2在不同的域,它们之间的session不共享也是没问题的。
Cookie的属性详细介绍:
name 名称,一旦创建,名称便不可更改
value 值,如果值为Unicode字符,需要为字符编码。如果值为二进制数据,则需要使用BASE64编码
maxAge 失效的时间,单位秒。正数,则该Cookie在maxAge秒之后失效。如果为负数,该Cookie为临时Cookie,关闭浏览器即失效,浏览器也不会以任何形式保存该Cookie。如果为0,表示删除该Cookie。默认为-1。
signed 所请求的cookie应该被签名
expires cookie 过期的 Date
path cookie 路径, 如果设置为“/sessionWeb/”,则只有contextPath为“/sessionWeb”的程序可以访问该Cookie。如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/”。默认是’/’,
domain cookie 域名。如果设置为“.google.com”,则所有以“google.com”结尾的域名都可以访问该Cookie。注意第一个字符必须为“.”。
secure 是否仅被使用安全协议传输。安全协议。安全协议有HTTPS,SSL等,在网络上传输数据之前先将数据加密。默认为false。
httpOnly 设置为true,则服务器可访问 cookie, 浏览器js脚本将无法读取到cookie信息,这样能有效的防止XSS攻击。默认是 true
overwrite 一个布尔值,表示是否覆盖以前设置的同名的 cookie (默认是 false). 如果是 true, 在同一个请求中设置相同名称的所有 Cookie(不管路径或域)是否在设置此Cookie 时从 Set-Cookie 消息头中过滤掉。
comment 用处说明
更多开发细节说明:
从客户端读取Cookie时,包括maxAge在内的其他属性都是不可读的,也不会被提交。浏览器提交Cookie时只会提交name与value属性。maxAge属性只被浏览器用来判断Cookie是否过期。
Cookie的修改、删除
Cookie并不提供修改、删除操作。如果要修改某个Cookie,只需要新建一个同名的Cookie,添加到response中覆盖原来的Cookie。
注意:修改、删除Cookie时,新建的Cookie除value、maxAge之外的所有属性,例如name、path、domain等,都要与原Cookie完全一样。否则,浏览器将视为两个不同的Cookie不予覆盖,导致修改、删除失败。
————————————————
版权声明:本文为CSDN博主「落花见流水」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_41913971/article/details/122609233