SSO三种情况的实现方式
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SSO三种情况的实现方式相关的知识,希望对你有一定的参考价值。
参考技术A 两个站点如果在同域下,那么它们之间是可以共享cookie的。简单的说就是这种同域下不同站点的sso实现可以通过cookie来实现,当用户访问这个域下面的任意站点时,浏览器都会将这个cookie发送给站点对应的系统。举个简单的例子:
站点1: www.ssotest.com/site1
站点2: www.ssotest.com/site2
从上面可以看出,这两个站点是在相同域名( www.ssotest.com )下,那么从站点1登录时,会在浏览器存储一些cookie,当在站点1下做任何操作时都会将这些cookie发送给站点1,同理,当访问站点2时,由于站点2和站点1在同一个域名下面,所以也会将这些cookie发送给站点2,所以这样的话就能够实现SSO了。可参考图1:
指相同父域,但是不同二级域名的单点登录,例如如下有两个站点:
从上面可以看出,它们的父域都是.ssotest.com,但是它们的二级域名不相同,所有如果在subsite1站点直接创建cookie,那么subsite2站点是不能够获取到subsite1的cookie的,所以如果直接在subsite1站点登录,将无法实现单点登录,那么如何才能实现这种情况的SSO呢?
实现它们之间的SSO最关键的一点是:实现cookie共享和session共享,保持二者的sessionId相同。
解决方案如下:
1.如果是使用的spring boot框架的后台应用,只需要在application.properties配置文件中添加上如下配置即可(因为内嵌tomcat):
2.如果使用外部tomcat,那么需要在server.xml文件中添加如下配置:
要实现这种跨域方式的SSO,有两种方式:
1.使用cookie,在各个应用之间重定向
2.使用单独的SSO服务器(更优)
那么下面详细的介绍上面这两种方式,以如下三个站点(应用)来具体描述:
这种方式比较简单,当用户在上面三个站点中的任意一个站点登录成功时,必须在浏览器中同时设置其他站点的cookie信息。
例如:当用户登录site1站点,并且验证通过之后,浏览器会存储一份site1站点的cookie信息,这时,为了实现单点登录(为了在site2站点和site3站点无需登录),那么我们需要在浏览器设置site2站点和site3站点的cookie信息,因此,在用户登录site1站点的请求响应之前,需要从siteId1站点重定向到site2站点和site3站点去设置cookie信息,这样就可以保证,在任意站点登录成功之后,在浏览器也有其他站点的cookie信息。下图2可具体展示其中流程:
这种方式其实过程比较简单,只需要确保登录其中一个站点在浏览器设置cookie其他站点都在浏览器设置对应cookie,就可以实现单点登录了(单点退出是一样的道理,一个退出清除cookie,其他也清除)。
但是这种方式有一个非常明显的缺点是:这里举例是3个站点,如果是几十个上百个站点再使用这种方式将非常影响效率。
这种方式需要借助一个单独的SSOServer,相对于上一种方式,这种方式就不需要将每个站点的cookie信息都保存在浏览器上,浏览器只需要保存SSOServer的cookie信息。将这个cookie信息用于需要做单点登录的所有站点中。
对于这种方式,在浏览器对于任意一个站点的请求都将会先重定向到SSOServer去验证代表当前用户的cookie是否存在,如果存在,那么将验证成功后的跳转页面发送给浏览器,否则将跳转到登录页面提示用户登录。可参考如下图3模型:
由于site1和site2的单点登录与site1、site2、site3之间的单点登录是同样道理的(因为登录site1后去访问site2和site3的流程都是相同的),所以,这里借助site1和site2的单点登录来说明这种方式。
下面分为三部分(三张图)来说明这种方式的单点登录:
第一部分:未在SSOServer登录,浏览器请求site1需要验证的页面,在SSOServer获取不到cookie,被重定向到site1登录界面,提示登录,流程如下图4:
在SSOServer登录的情况下,其他所有站点的登录情况都如site2,图6所示的流程,可见使用SSOServer的方式会方便许多。
以上就是SSO三种情况的实现方式。
单点登录的三种实现方式
单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。单点登录在大型网站里使用得非常频繁,例如像阿里巴巴这样的网站,在网站的背后是成百上千的子系统,用户一次操作或交易可能涉及到几十个子系统的协作,如果每个子系统都需要用户认证,不仅用户会疯掉,各子系统也会为这种重复认证授权的逻辑搞疯掉。实现单点登录说到底就是要解决如何产生和存储那个信任,再就是其他系统如何验证这个信任的有效性,因此要点也就以下两个:
- 存储信任
- 验证信任
如果一个系统做到了开头所讲的效果,也就算单点登录,单点登录有不同的实现方式,本文就罗列我开发中所遇见过的实现方式。
以Cookie作为凭证媒介
最简单的单点登录实现方式,是使用cookie作为媒介,存放用户凭证。
用户登录父应用之后,应用返回一个加密的cookie,当用户访问子应用的时候,携带上这个cookie,授权应用解密cookie并进行校验,校验通过则登录当前用户。
不难发现以上方式把信任存储在客户端的Cookie中,这种方式很容易令人质疑:
- Cookie不安全
- 不能跨域实现免登
对于第一个问题,通过加密Cookie可以保证安全性,当然这是在源代码不泄露的前提下。如果Cookie的加密算法泄露,攻击者通过伪造Cookie则可以伪造特定用户身份,这是很危险的。
对于第二个问题,更是硬伤。
通过JSONP实现
对于跨域问题,可以使用JSONP实现。
用户在父应用中登录后,跟Session匹配的Cookie会存到客户端中,当用户需要登录子应用的时候,授权应用访问父应用提供的JSONP接口,并在请求中带上父应用域名下的Cookie,父应用接收到请求,验证用户的登录状态,返回加密的信息,子应用通过解析返回来的加密信息来验证用户,如果通过验证则登录用户。
这种方式虽然能解决跨域问题,但是安全性其实跟把信任存储到Cookie是差不多的。如果一旦加密算法泄露了,攻击者可以在本地建立一个实现了登录接口的假冒父应用,通过绑定Host来把子应用发起的请求指向本地的假冒父应用,并作出回应。
因为攻击者完全可以按照加密算法来伪造响应请求,子应用接收到这个响应之后一样可以通过验证,并且登录特定用户。
通过页面重定向的方式
最后一种介绍的方式,是通过父应用和子应用来回重定向中进行通信,实现信息的安全传递。
父应用提供一个GET方式的登录接口,用户通过子应用重定向连接的方式访问这个接口,如果用户还没有登录,则返回一个的登录页面,用户输入账号密码进行登录。如果用户已经登录了,则生成加密的Token,并且重定向到子应用提供的验证Token的接口,通过解密和校验之后,子应用登录当前用户。
这种方式较前面两种方式,接解决了上面两种方法暴露出来的安全性问题和跨域的问题,但是并没有前面两种方式方便。
安全与方便,本来就是一对矛盾。
使用独立登录系统
一般说来,大型应用会把授权的逻辑与用户信息的相关逻辑独立成一个应用,称为用户中心。
用户中心不处理业务逻辑,只是处理用户信息的管理以及授权给第三方应用。第三方应用需要登录的时候,则把用户的登录请求转发给用户中心进行处理,用户处理完毕返回凭证,第三方应用验证凭证,通过后就登录用户。
以上是关于SSO三种情况的实现方式的主要内容,如果未能解决你的问题,请参考以下文章