谈谈单点登录

Python019

谈谈单点登录,第1张

寒假学习的小课题,把之前的笔记整理整理记录一下(长文警告)因为当时看到的东西涉及很多,所以有一些地方没有深入去探讨。

百度百科:单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

简而言之就是用户在多个相互信任的应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统。这里的关键是一次登录,以及一次退出,都对所有的系统生效。

在普通的登录中,比如典型的B/S情景,浏览器访问服务器,发送登录请求,在发送完用户名和密码之后,服务器会生成该用户的session来标准该用户的状态,比如已登录还是已注销,并给一个cookie给浏览器,因此,用户继续访问就会带上这个cookies,服务端会根据这个Cookie找到对应的session,通过session来判断这个用户的登录状态。比如php中使用phpsessid。当然也可以自定义session的生命周期,session的生命周期过长的话一旦session被盗用就会出现用户被窃取的情况。同时,生命周期过长的session配置会占用较多的服务器资源。

单点登录主要针对同平台下多应用,多系统的情景下多次登录的一种解决方案。单点登录相当于将多个应用的认证体系联通。

假设现在一个平台上有3个都带有登录功能的应用,由上面的普通登录的情况可以想到,这3台服务器都会自己的记录session。那么要想达到单点登录,一个最简单的方法就出现了:共享session。

共享session的方式来实现单点登录是最方便也是最直接的。在三个子系统中,使用同一个额外的记录session的服务器,比如我们可以使用一个redis服务器来存储三个系统的session。

用户登录了应用1,获取了应用1返回的cookies,再次访问应用1的其他功能的候携带了cookie就是已登录的状态了,但是这样又有新的问题,虽然实现了共享session,但是用户登录了应用1,获取了应用1返回的cookie,但是因为cookie是无法跨域的,因此用户无法使用应用1的cookie去访问应用2。这里我们就需要将系统的全局cookie domain的属性设置为顶级域名,比如应用1的域名是1.test.com,应用2的域名是2.test.com。在普通登录的情况下,应用1的cookie domain的属性是1.test.com,指这个cookie只能在该子域名上被使用。我们将系统的全局cookie domain设置为顶级域名,即.test.com,这样就可以实现用户登录了应用1,之后可以以已登录状态访问应用2和3。

上面的共享session的情况是三个应用都有登录功能,还有一种类似的情况是应用1和应用2都有登录模块和其他模块,还有一个单独的SSO系统,是仅有登录模块的:

共享session的方法虽然简单,但是存在局限性,因为使用了cookie顶域的特性,所以不能做到跨域。一个公司或者一个平台很可能不是所有的域名都在在一个一级域名之下的,所以同域名下的单点登录并不是完整的单点登录。

先说说openid,openid是一种认证标准,规定如何认证的标准!即其关注的是登录时身份的认证。官方给出的一个场景,其中一方是一个openid身份服务器,用来存放注册好的openid账号,另一方是受这个openid身份服务器信赖的服务或应用。openid协议就是提供openid身份服务器和被信赖的服务或应用之间的通信的。比如我们在很多网站上可以使用QQ登录,这里的腾讯的QQ就是openid的身份服务器,我们所要登录的网站就是受信赖的服务或应用。

在使用openid实现单点登录的方法有很多,可以使用上面共享session的方法,即把openid带在cookie里面,但是这样也会出现一样的cookie跨域的问题。

在实际场景中,我们在访问提供服务的应用时检测到未登录就会直接跳转到openid身份服务器,或者没有重定向而是在登录表单附近点击选择使用第三方openid登录,进行账号密码登录(这可以保证我们所登录的服务器无法获取我们的敏感身份认证信息),具体流程如下:

CAS全称为Central Authentication Service即中央认证服务,是一个企业多语言单点登录的解决方案,并努力去成为一个身份验证和授权需求的综合平台。CAS就是一个现成的单点登录的demo,企业只需要简单修改就可使用。

CAS支持各种协议,SAML,OAuth,OpenID,OIDC等等,支持LDAP,Radius,JWTX,509等等进行身份认证和授权,还有各种常用语言的客户端,Java,PHP,C# 等等。反正就是一个十分完整的,兼容性特别好的SSO框架。

简单了解CAS是如何实现单点登录的。在官网上可以看到其给出的一个 流程图 ,。这个图说的特别详细,一下就能看懂,直接原图上进行标注查看:

学习了上面几种单点登录的知识,结合实际场景可知,跨域单点登录才是真正的单点登录,因为实际情况下很多平台或者域名不可能都在一个一级域名下。在解决跨域单点登录的问题的时候,上面也给说了几种方式,但是究其根本,就是利用一个SSO认证中心来实现认证与授权的。当然,也会有其他的解决跨域单点登录的方案,但是大体流程都与cas类似。

比如在上图的11步骤,也可使用POST包,或者JSONP和iframe方法来跨域发送请求进行重定向。

在利用认证中心来实现单点登录是现在比较普遍的解决方案,那么有没有不需要使用认证中心来解决跨域单点登录的方案呢?

利用JSONP同步登录状态,大概流程流程如下:

在学习单点登录的过程中,在其中认证的过程中授权令牌的传递等相关信息没有特别详细的说明,而且在思考单点登录的时候也会有想过一个比较矛盾的问题:单点登录的目标是为了让用户可以在相互信任的系统中一次登录即可,但是如果真的是做到所有用户都可以访问所有系统,岂不是会带来越权的问题,是否需要对不同的用户以不同的授权,甚至限制访问的应用,但是这样是不是就不是原本狭义的单点认证?

在说单点登录的认证和授权之前,先谈一谈我一直想弄清楚的统一身份认证和单点登录的区别。说起单点登录可能很少听过,但是统一身份认证肯定不陌生,不管是企业还是高校都会有这种统一身份认证的系统。

统一身份认证最重要的一方面就是身份认证,另一方面就是和身份认证相关的授权控制,权限控制。而单点登录是多应用一次登录,也可以叫统一登录,可以理解为主要在认证方面。对于统一身份认证来说会有账号管理,如LDAP,认证管理OAuth,SMAL等,因此我觉得,统一身份认证一般是包括狭义的单点登录,狭义的单点登录,即只需要满足多应用一次登录即可。但是现在的单点登录,SSO系统并不仅仅是要求这些,他的范围正在慢慢扩大。

单点登录的认证和授权,前面说到的CAS实现单点登录里就会看到需要ticket来进行认证,授权。CAS支持多种认证方案,比如OAuth,OpenID,SAML等等,我们可以来比较比较用这些协议的区别,或者说是在哪些场景下使用哪些认证方案较为合适。本身单点登录是没有权限控制的功能的,但是因为这些认证协议的需求,自然支持了权限控制。

在使用SAML进行认证的过程中,可以看到下图,其是基本流程都差不多,这里需要注意的就是在用户在认证中心成功登陆之后,重定向的时候返回的是一个SAML token,一个XML节点,这里的token会包括用户的身份信息,用户名等。

在OAuth2.0的标准中流程是和上面的基本相同,但是OAuth2因为客户端并没有一点是浏览器,所以token中默认是没有签名的。这里可能没有体现出来,OAuth2的目标是授权,所以token更关注的是权限,token在向认证服务器验证的时候就会有不同的授权,但是既然是授权,就间接实现了认证。

在传统的认证中都是基于session机制的,具体的session模式上面也说了,根据其特性可知session的一些确定:

https://www.mutuallyhuman.com/blog/choosing-an-sso-strategy-saml-vs-oauth2/

https://yq.aliyun.com/articles/636281

https://juejin.im/post/5d0dbb7e6fb9a07f0420512d

<http use-expressions="true">

<intercept-url pattern="/**/*.do" access="hasAnyRole('user', 'admin')" />

<intercept-url pattern="/**/*.jsp" access="isAuthenticated()" method="GET" />

<form-login login-page="/login.jsp" />

<remember-me />

<logout logout-success-url="/loggedout.jsp" delete-cookies="JSESSIONID"/>

<session-management invalid-session-url="/timeout.jsp">

<concurrency-control max-sessions="5" error-if-maximum-exceeded="true" />

</session-management>

<custom-filter ref="mySecurityFilter" before="FILTER_SECURITY_INTERCEPTOR"/>

</http>

“只能登陆一次”还是“只允许单点登陆”

值能登陆一次实现方法:在退出的时候将该账号注销掉;

值允许单点登陆的方法:给用户po扩增一个登陆标识字段,通过该标识控制单点登陆;