如何实现 与windows 的sso

如题所述

1、windows域登录与SSO服务器整合
1.1 分析:windows域登录过程采用Kerberose v5协议进行登录,过程非常复杂,并且登录中身份认证以及域的权

限整合在一起。要剥离身份认证和权限赋权非常困难。要整合现有的SSO服务器,可以考虑,采用windows域控制器

统一管理用户,SSO服务器采用该域控制器的Active Directory中的用户信息。windows工作站(比如winxp)登录

域过程中,保持原域登录的过程,在其中添加SSO服务器的登录过程。
1.2 实现:通过修改GINA模块,在windows工作站(比如winxp)登录域过程中,winlogon调用GINA组模块,把用户

提供的账号和密码传达给GINA,由GINA负责在域控制器中以及SSO服务器中账号和密码的有效性验证,然后把验证

结果反馈给Winlogon程序,只有域控制器和SSO服务器同时认证成功,才是登录成功。
另外开发一个DLL程序,暂时称为SSOLogin模块,GINA在登录成功后,将SSO的登录信息传递给SSOLogin模块,动力

工作站在启动时,首先调用SSOLogin模块,判断已经登录的用户,然后通过动力工作站访问其他应用时,就可以通

过SSO服务器进行单点登录。
1.3 技术点:
(1)通过jCIFS实现SSO服务器在Active Directory进行域登录。
(2)采用WFC开发框架对GINA.dll进行修改,在注册表中进行注册
1.4 风险难点:(1)、windows域登录过程的分析与改造。(2)、windows的应用不开源,代码分析会比较困难。
1.5 其他:是否还考虑linux操作系统加入windows域的过程?

1.6 winxp登录域过程如下:
  (1).用户首先按Ctrl+Alt+Del组合键。
  (2).Winlogon检测到用户按下SAS键,就调用GINA,由GINA显示登录对话
框,以便用户输入账号和密码。
  (3).用户选择所要登录的域和填写账号与密码,确定后,GINA将用户输入的
信息发送给LSA进行验证。
  (4).在用户登录到本机的情况下,LSA将请求发送给Kerberos验证程序包。
通过散列算法,根据用户信息生成一个密钥,并将密钥存储在证书缓存区中。
  (5).Kerberos验证程序向KDC(Key Distribution Center--密钥分配中心)发
送一个包含用户身份信息和验证预处理数据的验证服务请求,其中包含用户证
书和散列算法加密时间的标记。
  (6).KDC接收到数据后,利用自己的密钥对请求中的时间标记进行解密,通
过解密的时间标记是否正确,就可以判断用户是否有效。
  (7).如果用户有效,KDC将向用户发送一个TGT(Ticket-Granting Ticket--
票据授予票据)。该TGT(AS_REP)将用户的密钥进行解密,其中包含会话密钥、
该会话密钥指向的用户名称、该票据的最大生命期以及其他一些可能需要的数
据和设置等。用户所申请的票据在KDC的密钥中被加密,并附着在AS_REP中。
在TGT的授权数据部分包含用户账号的SID以及该用户所属的全局组和通用组的
SID。注意,返回到LSA的SID包含用户的访问令牌。票据的最大生命期是由域
策略决定的。如果票据在活动的会话中超过期限,用户就必须申请新的票据。
  (8).当用户试图访问资源时,客户系统使用TGT从域控制器上的Kerberos
TGS请求服务票据(TGS_REQ)。然后TGS将服务票据(TGS_REP)发送给客户。该
服务票据是使用服务器的密钥进行加密的。同时,SID被Kerberos服务从TGT复
制到所有的Kerberos服务包含的子序列服务票据中。  
  (9).客户将票据直接提交到需要访问的网络服务上,通过服务票据就能证明
用户的标识和针对该服务的权限,以及服务对应用户的标识。
温馨提示:答案为网友推荐,仅供参考
第1个回答  2016-01-25
关键字: 单点登录 SSO Session
单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单点登录时,也会遇到一些小问题,在不同的应用环境中可以采用不同的单点登录实现方案来满足需求。我将以我所遇到的应用环境以及在其中所经历的各个阶段与大家分享,若有不足,希望各位不吝赐教。
一、共享Session
共享Session可谓是实现单点登录最直接、最简单的方式。将用户认证信息保存于Session中,即以Session内存储的值为用户凭证,这在单个站点内使用是很正常也很容易实现的,而在用户验证、用户信息管理与业务应用分离的场景下即会遇到单点登录的问题,在应用体系简单,子系统很少的情况下,可以考虑采用Session共享的方法来处理这个问题。
这个架构我使用了基于Redis的Session共享方案。将Session存储于Redis上,然后将整个系统的全局Cookie Domain设置于顶级域名上,这样SessionID就能在各个子系统间共享。

这个方案存在着严重的扩展性问题,首先,ASP.NET的Session存储必须为SessionStateItemCollection对象,而存储的结构是经过序列化后经过加密存储的。并且当用户访问应用时,他首先做的就是将存储容器里的所有内容全部取出,并且反序列化为SessionStateItemCollection对象。这就决定了他具有以下约束:

1、 Session中所涉及的类型必须是子系统中共同拥有的(即程序集、类型都需要一致),这导致Session的使用受到诸多限制;

2、 跨顶级域名的情况完全无法处理;

二、基于OpenId的单点登录

这种单点登录将用户的身份标识信息简化为OpenId存放于客户端,当用户登录某个子系统时,将OpenId传送到服务端,服务端根据OpenId构造用户验证信息,多用于C/S与B/S相结合的系统,流程如下

由上图可以看到,这套单点登录依赖于OpenId的传递,其验证的基础在于OpenId的存储以及发送。
   1、当用户第一次登录时,将用户名密码发送给验证服务;
   2、验证服务将用户标识OpenId返回到客户端;
   3、客户端进行存储;
   4、访问子系统时,将OpenId发送到子系统;
   5、子系统将OpenId转发到验证服务;
   6、验证服务将用户认证信息返回给子系统;
   7、子系统构建用户验证信息后将授权后的内容返回给客户端。
这套单点登录验证机制的主要问题在于他基于C/S架构下将用户的OpenId存储于客户端,在子系统之间发送OpenId,而B/S模式下要做到这一点就显得较为困难。为了处理这个问题我们将引出下一种方式,这种方式将解决B/S模式下的OpenId的存储、传递问题。
三、基于Cookie的OpenId存储方案
我们知道,Cookie的作用在于充当一个信息载体在Server端和Browser端进行信息传递,而Cookie一般是以域名为分割的,例如a.xxx.com与b.xxx.com的Cookie是不能互相访问的,但是子域名是可以访问上级域名的Cookie的。即a.xxx.com和b.xxx.com是可以访问xxx.com下的Cookie的,于是就能将顶级域名的Cookie作为OpenId的载体。
验证步骤和上第二个方法非常相似:
  1、 在提供验证服务的站点里登录;
  2、 将OpenId写入顶级域名Cookie里;
  3、 访问子系统(Cookie里带有OpenId)
  4、 子系统取出OpenId通过并向验证服务发送OpenId
  5、 返回用户认证信息
  6、 返回授权后的内容
在以上两种方法中我们都可以看到通过OpenId解耦了Session共享方案中的类型等问题,并且构造用户验证信息将更灵活,子系统间的验证是相互独立的,但是在第三种方案里,我们基于所有子系统都是同一个顶级域名的假设,而在实际生产环境里有多个域名是很正常的事情,那么就不得不考虑跨域问题究竟如何解决。
四、B/S多域名环境下的单点登录处理
在多个顶级域名的情况下,我们将无法让各个子系统的OpenId共享。处理B/S环境下的跨域问题,我们首先就应该想到JSONP的方案。
验证步骤如下:
  1、 用户通过登录子系统进行用户登录;
  2、 用户登录子系统记录了用户的登录状态、OpenId等信息;
  3、 用户使用业务子系统;
  4、 若用户未登录业务子系统则将用户跳转至用户登录子系统;
  5、 用户子系统通过JSONP接口将用户OpenId传给业务子系统;
  6、 业务子系统通过OpenId调用验证服务;
  7、 验证服务返回认证信息、业务子系统构造用户登录凭证;(此时用户客户端已经与子业务系统的验证信息已经一一对应)
  8、 将用户登录结果返回用户登录子系统,若成功登录则将用户跳转回业务子系统;
  9、 将授权后的内容返回客户端;

五、安全问题
经过以上步骤,跨域情况下的单点登录问题已经可以得到解决。而在整个开发过程初期,我们采用用户表中纪录一个OpenId字段来保存用户OpenId,而这个机制下很明显存在一些安全性、扩展性问题。这个扩展性问题主要体现在一个方面:OpenId的安全性和用户体验的矛盾。
整个单点登录的机制决定了OpenId是会出现在客户端的,所以OpenId需要有过期机制,假如用户在一个终端登录的话可以选择在用户每次登录或者每次退出时刷新OpenId,而在多终端登录的情况下就会出现矛盾:当一个终端刷新了OpenId之后其他终端将无法正常授权。而最终,我采用了单用户多OpenId的解决方案。每次用户通过用户名/密码登录时,产生一个OpenId保存在Redis里,并且设定过期时间,这样多个终端登录就会有多个OpenId与之对应,不再会存在一个OpenId失效所有终端验证都失效的情况。