大家好,好久不见,今天老吕给大家来一篇偏冷门知识的文章。
一、需求
大型集团企业内部会有许多业务系统,工作人员也往往需要登录多个业务系统才能完成工作,这就可能会存在一些问题
1、多套账号与密码需要记录或者记忆
2、多次登录,不太好的工作体验与工作效率
二、解决方案
问题的本质是需要一个企业内部工作人员办公时使用的单点登录SSO方案
方案1:
常用方案,统一账号系统,建立用户中心,统一用户创建与登录渠道,通过cas、oauth2、oidc等协议实现用户身份的传递与验证;
方案2:
基于域控的方案,将操作系统域账号与业务系统账号体系打通,通过kerberos、ntlm等安全协议实现用户身份的识别与传递;
本文主要讲解的是如何通过方案2来实现SSO
三、域控SSO的实现原理
在这个图中按角色划分有4个参与方
参与方1-域控服务器:
建立存储域账号密码(包括客户机账号与服务账号),同时实现了KDC功能;
参与方2-客户机:
同时和域控服务和SSO服务通信完成身份信息的传递;
参与方3-SSO服务:
这个就是开发人员需要开发的服务,目标是通过解密加密令牌来获得客户机身份信息,进一步将身份信息加密后通过IODC协议传给业务系统;
参与方4-业务系统:
可能是多个,他们通过对接SSO服务来获得专用密钥,从而可以解密加密的身份信息,最终获得可信的明文身份ID,进一步通过生成自身的登录令牌转向自有控制,从而登录成功。
四、安全认证协议Kerberos
Kerberos 是一种网络认证协议,其设计目标是通过密钥系统为客户机 / 服务器应用程序提供强大的认证服务。该认证过程的实现不依赖于主机操作系统的认证,无需基于主机地址的信任,不要求网络上所有主机的物理安全,并假定网络上传送的数据包可以被任意地读取、修改和插入数据。在以上情况下, Kerberos 作为一种可信任的第三方认证服务,是通过传统的密码技术(对称密钥)执行认证服务的。
kerberos协议交互过程如下:
其中:
AS_REQ内容主要为 :
1、用户名和客户端主机名信息 2、一个被client password hash加密的时间戳 3、明文的时间戳
AS_REP内容主要为:
1、SessionKey(被Client password hash 加密)
2、TGT=SessionKey+Client Info+ EndTime(TGT整体被KDC password hash加密)
TGS_REQ内容主要为:
1、TGT=SessionKey+Client Info+ EndTime(TGT整体被KDC password hash加密)
2、Client Info+Timestamp+ApplicationServerInfo(整体被SessionKey加密)
TGS_REP内容主要为:
1、Server Session Key(被SessionKey加密,用于和application server通信时加密数据)
2、ServiceTicket=ServerSessionKey+ClientInfo+EndTime(整体被Service password hash 加密)
AP_REQ内容主要为:
1、ServiceTicket
2、ClientInfo+Timestamp (整体被TGS颁发的Server Session Key加密)
AP_REP验票过程为:
1、applicat server会使用Service password hash对ServiceTicket进行解密从而得到ServerSessionKey,ClientInfo,EndTime
2、用ServerSessionKey解密另一段密文,从而得到 ClientInfo和Timestam信息
3、从而可以确认 ClientInfo的正确性,并得到身份ID信息
套路总结:
1、不停地签发临时密钥,使用临时密钥进行对称加密;
2、基于约定对称密钥再进行进一步对临时密钥和内容加密;
3、通过时间戳判断票据是否过期
五、基于Java实现kerberos单点登录
弄清楚了原理之后就可以开干了,SSO Service部分就是需要用Java代码实现的部分,这部分要实现的目标是:
1、通过HTTP标头 Authorization 来获取加密的票据信息
2、如果Authorization为空,则返回401状态码并且响应:WWW-Authenticate: Negotiate 标头,告诉客户端浏览器服务端能处理的认证机制
3、客户端会选择(OS提供GSS-API,浏览器会调用,从而得到客户端支持的认证机制)自身支持的、合适的认证机制(这个过程也叫认证协商过程)
4、window客户端的认证机制是:当前客户端加入了正确的域,并且当前访问使用了正确的域名访问SSO Service,这时会优先使用kerberos认证机制,其它情况优先使用NTLM认证机制
5、当服务端发现Authorization不是我们想要的协议票据时,接着返回401即可,直到得到我们想要的票据
6、假设最终服务端收到了kerberos票据,就需要对票据进行解密验证客户端身份了,如果验证通过就会得到明文的客户端登录账号信息
7、具体如何解密要参考Java 的JAAS api 对kerberos的支持
六、Java开源方案参考资源
1、Tomcat认证模块
(https://tomcat.apache.org/tomcat-9.0-doc/windows-auth-howto.html)
特点:依赖jaas,需要keytab文件,配置文件
2、Waffle
(http://waffle.codeplex.com/)
特点:不需要keytab文件,依赖native api
3、Spring Security - Kerberos Extension
http://static.springsource.org/spring-security/site/extensions/krb/index.html
4、Jespa
(http://www.ioplex.com/)
特点:收费,支持SPNEGO/Kerberos协议和ntlm v1
5、SPNEGO AD project at SourceForge 开源项目
(https://spnego.sourceforge.net/index.html)
特点:只支持SPNEGO/Kerberos协议
6、使用IIS做反向代理
2023第一篇,今天就到这里,谢谢大家支持!