单点登陆

单点登陆的技术实现机制
随着SSO技术的流行,SSO的产品也是满天飞扬。所有著名的软件厂商都提供了相应的解决方案。在这里我并不想介绍自己公司(Sun Microsystems)的产品,而是对SSO技术本身进行解析,并且提供自己开发这一类产品的方法和简单演示。有关我写这篇文章的目的,
单点登录的机制其实是比较简单的,用一个现实中的例子做比较。颐和园是北京著名的旅游景点,也是我常去的地方。在颐和园内部有许多独立的景点,例如“苏州街”、“佛香阁”和“德和园”,都可以在各个景点门口单独买票。很多游客需要游玩所有德景点,这种买票方式很不方便,需要在每个景点门口排队买票,钱包拿进拿出的,容易丢失,很不安全。于是绝大多数游客选择在大门口买一张通票(也叫套票),就可以玩遍所有的景点而不需要重新再买票。他们只需要在每个景点门口出示一下刚才买的套票就能够被允许进入每个独立的景点。
单点登录的机制也一样,如下图所示,当用户第一次访问应用系统1的时候,因为还没有登录,会被引导到认证系统中进行登录(1);根据用户提供的登录信息,认证系统进行身份效验,如果通过效验,应该返回给用户一个认证的凭据--ticket(2);用户再访问别的应用的时候(3,5)就会将这个ticket 带上,作为自己认证的凭据,应用系统接受到请求之后会把ticket送到认证系统进行效验,检查ticket的合法性(4,6)。如果通过效验,用户就可以在不用再次登录的情况下访问应用系统2和应用系统3了。
650) this.width=650;" onsubmit onchange onunload onselect onreset>
从上面的视图可以看出,要实现SSO,需要以下主要的功能:

  • 所有应用系统共享一个身份认证系统。
    统一的认证系统是SSO的前提之一。认证系统的主要功能是将用户的登录信息和用户信息库相比较,对用户进行登录认证;认证成功后,认证系统应该生成统一的认证标志(ticket),返还给用户。另外,认证系统还应该对ticket进行效验,判断其有效性。
  • 所有应用系统能够识别和提取ticket信息
    要实现SSO的功能,让用户只登录一次,就必须让应用系统能够识别已经登录过的用户。应用系统应该能对ticket进行识别和提取,通过与认证系统的通讯,能自动判断当前用户是否登录过,从而完成单点登录的功能。


上面的功能只是一个非常简单的SSO架构,在现实情况下的SSO有着更加复杂的结构。有两点需要指出的是:

  • 单一的用户信息数据库并不是必须的,有许多系统不能将所有的用户信息都集中存储,应该允许用户信息放置在不同的存储中,如下图所示。事实上,只要统一认证系统,统一ticket的产生和效验,无论用户信息存储在什么地方,都能实现单点登录。


650) this.width=650;" onsubmit onchange onunload onselect onreset>

  • 统一的认证系统并不是说只有单个的认证服务器,如下图所示,整个系统可以存在两个以上的认证服务器,这些服务器甚至可以是不同的产品。认证服务器之间要通过标准的通讯协议,互相交换认证信息,就能完成更高级别的单点登录。如下图,当用户在访问应用系统1时,由第一个认证服务器进行认证后,得到由此服务器产生的ticket。当他访问应用系统4的时候,认证服务器2能够识别此ticket是由第一个服务器产生的,通过认证服务器之间标准的通讯协议(例如SAML)来交换认证信息,仍然能够完成SSO的功能。


650) this.width=650;" onsubmit onchange onunload onselect onreset>
3 WEB-SSO的实现
随着互联网的高速发展,WEB应用几乎统治了绝大部分的软件应用系统,因此WEB-SSO是SSO应用当中最为流行。WEB-SSO有其自身的特点和优势,实现起来比较简单易用。很多商业软件和开源软件都有对WEB-SSO的实现。其中值得一提的是OpenSSO (https://opensso.dev.java.net),为用Java实现WEB-SSO提供架构指南和服务指南,为用户自己来实现WEB-SSO提供了理论的依据和实现的方法。 
为什么说WEB-SSO比较容易实现呢?这是有WEB应用自身的特点决定的。
众所周知,Web协议(也就是HTTP)是一个无状态的协议。一个Web应用由很多个Web页面组成,每个页面都有唯一的URL来定义。用户在浏览器的地址栏输入页面的URL,浏览器就会向Web Server去发送请求。如下图,浏览器向Web服务器发送了两个请求,申请了两个页面。这两个页面的请求是分别使用了两个单独的HTTP连接。所谓无状态的协议也就是表现在这里,浏览器和Web服务器会在第一个请求完成以后关闭连接通道,在第二个请求的时候重新建立连接。Web服务器并不区分哪个请求来自哪个客户端,对所有的请求都一视同仁,都是单独的连接。这样的方式大大区别于传统的(Client/Server)C/S结构,在那样的应用中,客户端和服务器端会建立一个长时间的专用的连接通道。正是因为有了无状态的特性,每个连接资源能够很快被其他客户端所重用,一台Web服务器才能够同时服务于成千上万的客户端。
650) this.width=650;" onsubmit onchange onunload onselect onreset>
但是我们通常的应用是有状态的。先不用提不同应用之间的SSO,在同一个应用中也需要保存用户的登录身份信息。例如用户在访问页面1的时候进行了登录,但是刚才也提到,客户端的每个请求都是单独的连接,当客户再次访问页面2的时候,如何才能告诉Web服务器,客户刚才已经登录过了呢?浏览器和服务器之间有约定:通过使用cookie技术来维护应用的状态。Cookie是可以被Web服务器设置的字符串,并且可以保存在浏览器中。如下图所示,当浏览器访问了页面1时,web服务器设置了一个cookie,并将这个cookie和页面1一起返回给浏览器,浏览器接到cookie之后,就会保存起来,在它访问页面2的时候会把这个cookie也带上,Web服务器接到请求时也能读出cookie的值,根据cookie值的内容就可以判断和恢复一些用户的信息状态。
650) this.width=650;" onsubmit onchange onunload onselect onreset>
Web-SSO完全可以利用Cookie结束来完成用户登录信息的保存,将浏览器中的Cookie和上文中的Ticket结合起来,完成SSO的功能。
为了完成一个简单的SSO的功能,需要两个部分的合作:

  • 统一的身份认证服务。
  • 修改Web应用,使得每个应用都通过这个统一的认证服务来进行身份效验

 

------------------------------------------------------------------------------------------------

1. 单点登录简介
1.1CAS简介

CAS 是 Yale (耶鲁)大学发起的一个开源项目,旨在为 Web 应用系统提供一种可靠的单点登录方法,CAS 在 2004 年 12 月正式成为 JA-SIG 的一个项目。

http://www.jasig.org/cas

CAS 具有以下特点:

基于kerberos身份认证协议技术

开源的企业级单点登录解决方案。

CAS Server 为需要独立部署的 Web 应用。

CAS Client 支持非常多的客户端(这里指单点登录系统中的各个 Web 应用),包括 Java, .Net, PHP, Perl, Apache, uPortal, Ruby 等。

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的基本功能是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。
例如:
A和B两个完全独立的系统分别有各自完全独立的用户管理,现在需要将这两个系统整合,不管是A系统中的帐户,还是B系统中的帐户,都只需要登录一次,就可以访问A和B系统的服务了。
如果一个人同时具有A和B系统的帐户,当他以A系统的帐户登录后,访问B系统时,B系统自动将它转换成本系统帐户再进行访问操作,反之亦然。
A和B系统整合后,不再单独提供新用户注册功能。新用户注册统一到中央认证管理系统中,新注册的用户可以同时访问A和B系统,例如,sina和sohu等网站的通行证注册就是这么回事。
1.2 关键字

KDC( Key Distribution Center ) ---------- 密钥发放中心

authentication service (AS) --------- 认证用服务,索取 Crendential ,发放 TGT

Ticket Granting tieckt(TGT) --------- 票据授权票据,由 KDC 的 AS 发放。即获取这样一张票据后,以后申请各种其他服务票据 (ST) 便不必再向 KDC 提交身份认证信息 ( 准确术语是 Credentials)

ticket-granting service (TGS) --------- 票据授权服务,索取 TGT ,发放 ST ,CAS 单点服务器的认证过程,所有应用服务器收到应用请求后,检查 ST 和 TGT ,如果没有或不对,转到 CAS 认证服务器登陆页面,通过安全认证后得到 ST 和 TGT 再重定向到相关应用服务器,在会话生命周期之内如果再定向到别的应用,将出示ST 和 TGT 进行认证 , 注意 , 取得 TGT 的过程是通过 SSL 安全协议的 ( 换句话说就是如果不用 ssl 协议 , 每访问一个应用服务,就得重新到认证服务中心认证一次 )。

Service ticket(ST) --------- 服务票据, 由 KDC 的 TGS 发放。 任何一台 Workstation 都需要拥有一张有效的 Service Ticket 才能访问域内部的应用 (Applications) 。如果能正确接收 Service Ticket ,说明在CASClient-CASServer 之间的信任关系已经被正确建立起来 , 通常为一张数字加密的证书

TGC(ticket-granting cookie) --------- 票据授权票Cookie(Ticket Grangting Cookie) 。在用户成功登录后,在CAS Server的Cookie中保存登录成功信息。在访问其他应用时,根据TGC去验证获取用户的登录信息

1.3 单点登录原理


cas 实现single sign out的原理,如图所示:

 

2011-4-5 22:24 上传
下载附件 (25.17 KB)

 

图一

第一张图演示了单点登陆的工作原理。

 

 

 

 

 

从第一张图中,当一个web浏览器登录到应用服务器时,应用服务器(application)会检测用户的session,如果没有登记过(登录),则应用服务器会把url跳转到CAS server上,要求用户登录,用户登录成功后,CAS server会记请求的application的url和该用户的sessionId(在应用服务器跳转url时,通过参数传给CAS server)。此时在CAS服务器会种下TGC Cookie值到webbrowser.拥有该TGC Cookie的webbrowser可以无需登录进入所有建立sso服务的应用服务器application。

 

2011-4-5 22:25 上传
下载附件 (38.92 KB)

 



图二
图二演示了单点登出的工作原理。
在第二张图中,当一个web浏览器要求登退应用服务器,应用服务器(application)会把url跳转到CAS server上的 /cas/logout url资源上,
CAS server接受请求后,会检测用户的TCG Cookie,把对应的session清除,同时会找到所有通过该TGC sso登录的应用服务器URL提交请求,所有的回调请求中,包含一个参数logoutRequest, logoutRequest包含:NameID,SessionIndex,所有收到请求的应用服务器application会解析这个参数,取得sessionId,根据这个Id取得session后,把session删除。
这样就实现单点登出的功能。

认证过程:

 

 

2011-4-5 22:28 上传
下载附件 (35.8 KB)

 

 

 

 

 

白话描述:

单点登陆,无非就是提供给用户一次登陆, 多个系统共享用户信息的操作。

这个是怎么操作的呢 ? 有简单的方法 , 当用户访问其他系统的时候 , 写个 URL 带上用户的 ID 和 PASS 提交到相应的系统就可以了。这也是一种方法。

那 CAS 是怎么操作的呢 ? 或则是 KRB(Kerberos 是一个加密认证协议,允许网络用户不使用明文密码访问服务,一个普通的协议实现包括 LOGIN 服务存在伪造欺骗对 Key Distribution Center 的响应。

怎么操作的呢 ?

 

2011-4-5 22:29 上传
下载附件 (74.91 KB)

 

他并不是很复杂 , 他先是建立一个专门认证用户的 服务 (SERVER) 这个服务只做一件事 , 负责验证用户的 ID 和 PASS 是否是正确 , 在正确的情况提供用户一个名为 TGT 的票据 , 相当你要去游乐场玩 , 首先你要在门口检查你的身份 ( 即 CHECK 你的 ID 和 PASS), 如果你通过验证 , 游乐场的票务中心 (AS) 即提供给你一张门卡 (TGT),同时把TGC保存到你的cookie(仅包含用户名等对安全不是很敏感的信息)。

这张卡片的用处就是告诉 游乐场的各个场所 , 你是通过正门进来 , 而不是后门偷爬进来的 , 并且也是获取进入场所一把钥匙。

好的, 现在你有张卡, 但是这对你来不重要, 因为你来游乐场不是为了拿这张卡的 , 好的 , 我们向你的目的出发, 恩, 你来到一个摩天楼 , 你想进入玩玩 , 这时摩天轮的服务员 (client) 拦下你 , 向你要求摩天轮的 (ST) 票据 , 你说你只有一个门卡 (TGT), 好的 , 那你只要把 TGT 放在一旁的票据授权机 (TGS) 上刷一下 , 票据授权机 (TGS) 就根据你现在所在的摩天轮 , 给你一张摩天轮的票据 (ST) , 现在你可以畅通无阻的进入摩天轮里游玩了。

当然如果你玩完摩天轮后 , 想去游乐园的咖啡厅休息下 , 那你一样只要带着那张门卡 (TGT). 到相应的咖啡厅的票据授权机 (TGS) 刷一下 , 得到咖啡厅的票据 (ST) 就可以进入咖啡厅。

 

 

2011-4-5 22:32 上传
下载附件 (42.72 KB)

 

从咖啡馆出来,女朋友说还想玩摩天轮,ok,你们又来到摩天轮,摩天轮工作人员一看你们有ST (第一次来的时候,TGS已经签发ST给你的TGT了)就直接放行。不让你们再跑到CAS那边去索取摩天轮的ST了,同样的,你们再此进入咖啡厅也是如此。


 

当你离开游乐场后 , 想用这张 TGT 去进去玩大摆锤 , 呵呵 , 对不起 , 你的 TGT 已经过期了 , 在你离开游乐场那刻开始 , 你的 TGT和TGC 就已经销毁了。想玩吗?想玩重新去注册吧(登录)

1.4 生命周期

TGT生命周期是通过配置文件设定的,默认2小时,失效后自动回收

TGC生命周期和TGT一样。

ST生命周期为一个服务进行一次认证的过程

Assertion生命周期为Session Timeout


1.5 Spring Security介绍

1、为基于J2EE企业应用提供了全面安全服务


 

1,将系统的安全逻辑从业务中分离出来

2,提供很多认证授权策略

3,基于URL的WEB资源访问控制

4,业务方法调用访问控制

5,领域对象访问控制
Access Control List(ACL)

6,单点登录(Central Authentication Service) 缓存、信道安全(Channel Security)管理等功能


1.5 Srping Security原理

1)、安全包括认证授权两个主要操作。


 

“认证”是为用户建立一个他所声明的主体。主体一般是指用户,设备或可以在你系统中执行行动的其他系统。


 

“授权”指的一个用户能否在你的应用中执行某个操作。在到达授权判断之前,身份的主体已经由身份验证过程建立了。

用户认证过程:

1.你点击一个链接访问一个网页;

2.浏览器发送一个请求到服务器,服务器判断出你正在访问一个受保护的资源;

3.如果此时你并未通过身份认证,服务器发回一个响应提示你进行认证——这个响应可能是一个HTTP响应代码,抑或重定向到一个指定页面;

4.根据系统使用认证机制的不同,浏览器或者重定向到一个登录页面中,或者由浏览器通过一些其它的方式获取你的身份信息(如通过BASIC认证对话框、一个Cookie);

5.浏览器再次将用户身份信息发送到服务器上(可能是一个用户登录表单的HTTP POST信息、也可能是包含认证信息的HTTP报文头);

6.服务器判断用户认证信息是否有效,如果无效,一般情况下,浏览器会要求你继续尝试,这意味着返回第3步。如果有效,则到达下一步;

7.服务器重新响应第2步所提交的原始请求,并判断该请求所访问的程序资源是否在你的权限范围内,如果你有权访问,请求将得到正确的执行并返回结果。否则,你将收到一个HTTP 403错误,这意味着你被禁止访问。

授权过程

Spring Security称受保护的应用资源为“安全对象”,这包括URL资源和业务类方法。spring AOP中有前置advice(处理、拦截器、通知)、后置advice 、异常advice和环绕advice 。Acegi使用环绕advice对安全对象进行保护。 Acegi通AbstractSecurityInterceptor为安全对象访问提供一致的工作模型,它按照以下流程进行工作:

1. 从SecurityContext中取出已经认证过的Authentication(包括权限信息);

2. 通过反射机制,根据目标安全对象和“配置属性”得到访问目标安全对象所需的权限;

3. AccessDecisionManager根据Authentication的授权信息和目标安全对象所需权限做出是否有权访问的判断。如果无权访问,Acegi将抛出AccessDeniedException异常,否则到下一步;

4. 访问安全对象并获取结果(返回值或HTTP响应);

5. AbstractSecurityInterceptor可以在结果返回前进行处理:更改结果或抛出异常。


1.6 Spring Security标签库

如果需要使用taglib,首先要把spring-security-taglibs-2.0.6.jar放到项目的classpath下。剩下的只要在jsp上添加taglib的定义就可以使用标签库了。

<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags"%>

1.6.1 Authenticaiton

authentication的功能是从SecurityContext中获得一些权限相关的信息。

可以用它获得当前登陆的用户名:

<sec:authentication property="name"/>

获得当前用户所有的权限,把权限列表放到authorities变量里,然后循环输出权限信息:

<sec:authentication property="authorities" var="authorities" scope="page"/>

<c:forEach items="${authorities}" var="authority">

${authority.authority}

</c:forEach>

1.6.2 authorize

authorize用来判断当前用户的权限,然后根据指定的条件判断是否显示内部的内容。

<sec:authorize ifAllGranted="ROLE_ADMIN,ROLE_USER">

admin and user

</sec:authorize>

<sec:authorize ifAnyGranted="ROLE_ADMIN,ROLE_USER">

admin or user

</sec:authorize>

<sec:authorize ifNotGranted="ROLE_ADMIN">

not admin

</sec:authorize>

说明:

1,ifAllGranted,只有当前用户同时拥有ROLE_ADMIN和ROLE_USER两个权限时,才能显示

标签内部内容。

2,ifAnyGranted,如果当前用户拥有ROLE_ADMIN或ROLE_USER其中一个权限时,就能显示

标签内部内容。

3,ifNotGranted,如果当前用户没有ROLE_ADMIN时,才能显示标签内部内容。



2 Spring Security与CAS集成
2.1 Spring Security与CAS集成

1.Spring Security与CAS可以无缝集成

Spring Security支持所有主流的认证方式,HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。CAS也是其中之一。

2.Spring Security与CAS有两种集成方式

第一种方式:Spring使用由Filter组成的Chain,来判断权限。如果Spring提供的Filter不能满足系统的权限功能,开发者可以自定义Filter,然后把Filter放在某个Filter Chain的某个位置。可以替换掉原有Filter Chain的某个Filter,也可以放在某个Filter之前或者之后。关于认证CAS提供两个filter。

第二种方式:Spring Security中自带关于CAS认证方式的组件。经过配置Spring Security自带的CasProcessingFilter和CasAuthenticationProvider即可。


2.2 通过数据库管理权限和资源

举例说明下:

 

 

2011-4-5 22:33 上传
下载附件 (42.1 KB)

 

如上图,利用intercept-url来判断用户需要具有何种权限才能访问对应的url资源,可以在pattern中指定一个特定的url资源,也可以使用通配符指定一组类似的url资源。例子中定义的两个intercepter-url,第一个用来控制对/admin.jsp的访问,第二个使用了通配符/**,说明它将控制对系统中所有url资源的访问。

在实际使用中,Spring Security采用的是一种就近原则,就是说当用户访问的url资源满足多个intercepter-url时,系统将使用第一个符合条件的intercept-url进行权限控制。在我们这个例子中就是,当用户访问/admin.jsp时,虽然两个intercept-url都满足要求,但因为第一个intercept-url排在上面,所以Spring Security会使用第一个intercept-url中的配置处理对/admin.jsp的请求,也就是说,只有那些拥有了ROLE_ADMIN权限的用户才能访问/admin.jsp。user-service中定义了两个用户,admin和user。为了简便起见,我们使用明文定义了两个用户对应的密码,是为了当前演示的方便(实际应用中我们会使用CAS来验证用户信息,这里只需配置用户和角色就可以了)最最重要的部分是authorities,这里定义了这个用户登陆之后将会拥有的权限,它与上面intercept-url中定义的权限内容一一对应。每个用户可以同时拥有多个权限,例子中的admin用户就拥有ROLE_ADMIN和ROLE_USER两种权限,这使得admin用户在登陆之后可以访问ROLE_ADMIN和ROLE_USER允许访问的所有资源。与之对应的是,user用户就只拥有ROLE_USER权限,所以他只能访问ROLE_USER允许访问的资源,而不能访问ROLE_ADMIN允许访问的资源。


 

当然实际应用中,资源信息和用户角色信息都是通过数据库来进行维护的,如下图:

user用户表,role角色表,resc资源表相互独立,它们通过各自之间的连接表实现多对

多关系。

 

 

 

 

 

 

 

 

 

 

查询数据库得到的数据如下:

用户角色信息:

 

2011-4-5 22:36 上传
下载附件 (3.74 KB)

 

角色资源信息(访问URL所需角色):

 

 

2011-4-5 22:37 上传
下载附件 (3.9 KB)

 

上图中,1,用户admin具有R_ADMIN角色,角色资源表中,R_ADMIN角色可以访问:/jsp/admin/**和jps/user/**,那么admin就可以访问/jsp/admin/**资源和jps/user/**

2,user用户具有R_USER角色,角色资源表中,R_USER角色可以访问/jsp/user/**,那么user用户就只能访问/jsp/user/**下的资源,而不能其他的资源

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值