cas单点登录实现原理浅析
一晃几个月没写博客了,今年多灾多难的一年。
安能摧眉折腰事权贵,使我不得开心颜!
财富是对认知的补偿,不是对勤奋的嘉奖。勤奋只能解决温饱,要挣到钱就得预知风口,或者有独到见解。
九十年代随便开个厂,随便造锅碗瓢盆就能挣到钱,这是人们生活变好对物质的逐渐增加。零几年的时候开个网吧,没日没夜挣钱,互联网兴起,人们开始追求精神需求。08年之前的房地产是朝阳产业,但凡贷款买几套房,后面卖出都能躺平下半生,这是城市化的风口。一几年的移动互联繁荣,催生了程序员等行业的快速发展,阿里京东等崭露头角,小米应运而生,这是科技的风口。现阶段看是流量为王,直播,短视频比较火。
一、基本流程介绍
CAS 包含两个部分:
CAS Server 和 CAS Client
。
CAS-Server 需要独立部署,主要负责对用户的认证工作;
CAS-Client 负责处理对客户端受保护资源的访问请求,需要登录时,重定向到 CAS Server
SSO单点登录访问流程步骤:
访问服务:SSO客户端发送请求访问应用系统提供的服务资源。
定向认证:SSO客户端会重定向用户请求到SSO服务器。
用户认证:用户身份认证。
发放票据:SSO服务器会产生一个随机的Service Ticket。
验证票据:SSO服务器验证票据Service Ticket的合法性,验证通过后,允许客户端访问服务。
传输用户信息:SSO服务器验证票据通过后,传输用户认证结果信息给客户端。
二、常用概念
TGT:Ticket Granted Ticket(俗称大令牌,或者说票根,他可以签发ST)
TGC:Ticket Granted Cookie(cookie中的value),存在Cookie中,根据他可以找到TGT。
ST:Service Ticket (小令牌),是TGT生成的,默认是用一次就生效了。也就ticket值
以我做过的一个经验为例:
TGC
是一个随机字符串,Ids.uuid()。
TGT
是包含用户信息的对象。 登录成功后,会保存redis,key就是TGC,value就是用户信息对象(可简称userInfo)
ST
即ticket
是一个随机字符串,登录成功后会存redis,key是ticket,value是包含TGC的对象同时,把TGC存在浏览器中
WebUtil.setCookie(response, “TGC”, tgc, -1)
WebUtil.setCookie 是我们自己的往浏览器存cookie的方法
也可大致理解为:
{TGC:TGT} {ticket:TGC}
三、流程图
详解流程:
-
- 用户访问办公系统
用户访问http://oa.sinux.com,经过过滤器(默认OA系统已经引入了cas-client的客户端)cas-client-sdk.jar。
该sdk的核心是实现了Filter接口的拦截器
主要作用:判断是否登录,如果没有登录则重定向到认证中心
-
- 重定向到cas认证中心
cas拦截器发现既没有ticket也没有登录态,那就直接
重定向
到cas服务端。
返回的url是:http://cas.sinux.com?service=http%3A%2F%2Foa.sinux.com%2F
后端使用重定向,浏览器获取到的Status Code 是302
注:这里的serice后的地址会经过编码过,URLEncoder.encode
-
- 请求到cas服务端
服务端会去获取cookie是否有TGC,如果没有,会弹出登录页。如果有会校验TGC,正确的话直接颁发ticket
-
- cas返回登录页面
cas服务端会重定向到自己的登录页面(即 idaas的登录页)
请求地址:http://cas.sinux.com?service=http%3A%2F%2Foa.sinux.com%2F
-
- 输入账密登录
用户输入账号密码
- 输入账密登录
-
- 校验账密(核心)
6.1 输入账密后会访问cas服务端的认证接口,例如/cas/login
http://cas.sinux.com/cas/login?service=http%3A%2F%2Foa.sinux.com%2F
参数就是输入的账号密码6.2 校验账密 - 校验逻辑不赘述
6.3 从cookie再去取一次TGC,再看看缓存是否存有以TGC为key的TGT的值,不存在则生成一个随机字符串作TGC,TGT则则包含了用户信息的对象,并缓存到redis
6.4 把TGC的值缓存到cookie,key就是TGC,value就是刚生成的随机字符串tgc
WebUtil.setCookie(response,“TGC”, tgc, -1);6.5 生成一个随机字符串作为ticket,并把ticket作为key,包含TGC的对象作为value缓存到redis
6.6 重定向service地址,并带上ticket 例如:http://oa.sinux.com?ticket=uaxdtejakj
-
- 浏览器发起重定向
浏览器收到302重定向到http://oa.sinux.com
-
- cas-client发起校验ticket
过滤器中会取到ticket的值,然后通过http方式调用http://cas.sinux.com验证该ticket是否是有效的
-
- cas服务端校验并返回
服务端根据ticket获取包含TGC的对象值,并删除ticket(一次有效),返回用户信息
-
- oa系统存储用户信息并返回资源
oa系统接收到cas服务端返回的用户信息,把用户信息存在session或redis,可以就是uuid,value就是用户信息。并往cookie存一个标识,用来保存uuid,例如:
CookieUtils.addCookie(response, “pa-ilf”, uuid, null, -1, false,false);
并通过拦截器的拦截,直接进入接口内容
-
- 用户再次访问OA系统
用户再次访问OA,因为cookie里有pa-if表示,可以拿到uuid,在拦截器里面可以拿到缓存的用户信息,直接通过拦截器进入接口
-
- 返回接口资源
返回接口信息
-
- 用户访问邮件系统
http://mail.sinux.com
-
- 邮箱系统发现第一次访问,拦截器拦截
邮箱系统(这里默认也对接了cas系统,即引入了cas-client包),发现无用户态无ticket,直接跳转到cas服务端地址(重定向)
http://cas.sinux.com?service=http%3A%2F%2Fmail.sinux.com%2F
-
- cas服务系统返回ticket
因为上面6.4已经在cookie缓存了一个TGC:uuid的结构,这里或直接拿到TGC的值即uuid,并取到用户信息。用户重新生成一个ticket,ticket与包含tgc的对象绑定 ,并把ticket拼接到url后面返回
-
- 返回浏览器
带ticket,并重定向
http://mail.sinux.com?ticket=dfgrtgaerwe
-
- 重定向回邮箱系统
浏览器收到302
http://mail.sinux.com?ticket=dfgrtgaerwe
拦截器发现没有登录态,回继续拦截
-
- 校验ticket(类似第8步)
cas-client发起http请求校验ticket的正确性
-
- 返回用户信息(类似第9步)
服务端根据ticket获取包含TGC的对象值,并删除ticket(一次有效),返回用户信息
-
- 缓存用户信息,并返回(类似第10步)
邮件系统接收到cas服务端返回的用户信息,把用户信息存在session或redis,可以就是uuid,value就是用户信息。并往cookie存一个标识,用来保存uuid,例如:
CookieUtils.addCookie(response, “pa-ilf”, uuid, null, -1, false,false);
并通过拦截器的拦截,直接进入接口内容
-
- 用户再次访问邮件系统
cas-client端会从cookie获取到pa-if对应的uuid,再根据uuid从缓存获取到用户信息, 那么久无需登录,直接进入接口
-
- 返回
返回接口资源