너겟 성장 여정을 시작하세요! "너겟데일리 신규 프로젝트·2월 업데이트 챌린지"에 처음 참여한 날입니다. 이벤트 내용 자세히 보기 클릭
안녕하세요 여러분 룻입니다. JWT
이전 에 인터뷰 형식으로 SSO(Single Sign-On)를 구현하는 디자인 아이디어에 대해 이야기했고 마지막에는 그것이 무엇인지에 대한 질문도 남겼습니다 CAS
.
아직 읽지 않은 학생들은 아래 링크를 클릭하여 먼저 읽을 것을 제안합니다. 둘은 여전히 어느 정도 일관성이 있습니다.
유쾌한 시작
오늘은 첫 출근이다. 처음 회사에 들어왔을 때 지난번 면접관을 봤다. 체크무늬 셔츠에 슬리퍼를 신고 있었다. 그를 Lao Yu라고 부르자. Lao Yu는 저를 보자마자 전화를 걸어 수다를 떨었는데, 최근에 본 소년의 노래 라인에 있는 누군가와 매우 낯익은 모습이었습니다.
CAS 란 무엇입니까?
Lao Yu: 지난 번에 언급하셨는데 CAS
, CAS
그게 뭐라고 생각하세요?
JWT
나: 예전에 인터뷰 할 때 Single Sign-On으로 인해 발생하는 문제에 대해 이야기하고 점차 최적화하여 마침내 중앙 집중식 Single Sign-On 시스템, 즉 CAS
솔루션으로 발전했습니다.
중앙 인증 서비스인 CAS(중앙 인증 서비스)는 단일 사인온의 특정 구현입니다. 로그인 전환 스테이션으로 이해할 수 있습니다. SSO
사이트를 통해 Cookie
도메인 간 문제를 해결할뿐만 아니라 SSO
서버를 통한 로그인 인증의 중앙 집중화를 실현합니다.
여기서 SSO는 다음을 의미합니다. SSO 시스템
디자인 프로세스는 어떻습니까
Lao Yu: 그 실현에 대한 일반적인 아이디어에 대해 말씀해 주시겠습니까? 이것은 너무 공허합니다. 당신이 말해야 할 것을 듣는 것과 같습니다.
나: 걱정하지 마세요. 먼저 공식 흐름도를 살펴보세요.
SSO로 리디렉션
우선, 사용자가 시스템 A의 1페이지에 접근하고자 한다면 자연스럽게 www.chezhe1.com
제한된 인터페이스(예를 들어, 사용자 정보 및 기타 인터페이스는 로그인 후에만 접근 가능)를 호출하게 됩니다.
接下来 系统A 服务端一般会在拦截器【也可以是过滤器,AOP 啥的】中根据Cookie
中的SessionId
判断用户是否已登录。如果未登录,则重定向到SSO
系统的登录页面,并且带上自己的回调地址,便于用户在SSO
系统登录成功后返回。此时回调地址是:www.sso.com?url=www.chezhe1.com
。
这个回调地址大家应该都不会陌生吧,像那种异步接口或者微信授权、支付都会涉及到这块内容。不是很了解的下面会解释~
另外这个回调地址还必须是前端页面地址,主要用于回调后和当前系统建立会话。
此时如下图所示:
用户登录
- 在重定向到
SSO
登录页后,需要在页面加载时调用接口,根据SessionId
判断当前用户在SSO
系统下是否已登录。【注意这时候已经在 SSO 系统的域名下了,也就意味着此时Cookie
中的domain
已经变成了sso.com
】
为什么又要判断是否登录?因为在 CAS 这个方案中,只有在SSO系统中为登录状态才能表明用户已登录。
- 如果未登录,展现账号密码框,让用户输入后进行
SSO
系统的登录。登录成功后,SSO
页面和SSO
服务端建立起了会话。 此时流程图如下所示:
安全验证
老余:你这里有一个很大的漏洞你发现没有?
我:emm,我当然知道。
对于中心化系统,我们一般会分发对应的AppId
,然后要求每个应用设置白名单域名。所以在这里我们还得验证AppId
的有效性,白名单域名和回调地址域名是否匹配。否则有些人在回调地址上写个黄色网站那不是凉凉。
获取用户信息登录
- 在正常的系统中用户登录后,一般需要跳转到业务界面。但是在
SSO
系统登录后,需要跳转到原先的系统A,这个系统A地址怎么来?还记得重定向到SSO
页面时带的回调地址吗?
通过这个回调地址,我们就能很轻易的在用户登录成功后,返回到原先的业务系统。
- 于是用户登录成功后根据回调地址,带上
ticket
,重定向回系统A,重定向地址为:www.chezhe1.com?ticket=123456a
。 - 接着根据
ticket
,从SSO
服务端中获取Token
。在此过程中,需要对ticket
进行验证。 - 根据
token
从SSO
服务端中获取用户信息。在此过程中,需要对token
进行验证。 - 获取用户信息后进行登录,至此系统A页面和系统A服务端建立起了会话,登录成功。
此时流程图如下所示:
别以为这么快就结束了哦,我这边提出几个问题,只有把这些想明白了,才算是真的清楚了。
- 为什么需要 Ticket?
- 验证 Ticket 需要验证哪些内容?
- 为什么需要 Token?
- 验证 Token 需要验证哪些内容?
- 如果没有Token,我直接通过Ticket 获取用户信息是否可行?
为什么需要 Ticket
我们可以反着想,如果没有Ticket
,我们该用哪种方式获取Token
或者说用户信息?你又该怎么证明你已经登录成功?用Cookie
吗,明显是不行的。
所以说,Ticket
是一个凭证,是当前用户登录成功后的产物。没了它,你证明不了你自己。
验证 Ticket 需要验证哪些内容
- 签名:对于这种中心化系统,为了安全,绝大数接口请求都会有着验签机制,也就是验证这个数据是否被篡改。至于验签的具体实现,五花八门都有。
- 真实性:验签成功后拿到
Ticket
,需要验证Ticket
是否是真实存在的,不能说随便造一个我就给你返回Token
吧。 - 使用次数:为了安全性,
Ticket
只能使用一次,否则就报错,因为Ticket
很多情况下是拼接在URL
上的,肉眼可见。 - 有效期:另外则是
Ticket
的时效,超过一定时间内,这个Ticket
会过期。比如微信授权的Code
只有5分钟的有效期。 - ......
为什么需要 Token?
只有通过Token
我们才能从SSO
系统中获取用户信息,但是为什么需要Token
呢?我直接通过Ticket
获取用户信息不行吗?
答案当然是不行的,首先为了保证安全性,Ticket
只能使用一次,另外Ticket
具有时效性。但这与某些系统的业务存在一定冲突。因此通过使用Token
增加有效时间,同时保证重复使用。
验证 Token 需要验证哪些内容?
和验证 Ticket类似
- 签名 2. 真实性 3. 有效期
如果没有 Token,我直接通过 Ticket 获取用户信息是否可行?
这个内容其实上面已经给出答案了,从实现上是可行的,从设计上不应该,因为Ticket
和Token
的职责不一样,Ticket
是登录成功的票据,Token
是获取用户信息的票据。
用户登录系统B流程
老余:系统A登录成功后,那系统B的流程呢?
我:那就更简单了。
比如说此时用户想要访问系统B,www.chezhe2.com
的限制接口,系统B服务端一般会在拦截器【也可以是过滤器,AOP 啥的】中根据Cookie
中的SessionId
判断用户是否已登录。此时在系统B中该系统肯定未登录,于是重定向到SSO
系统的登录页面,并且带上自己的回调地址,便于用户在SSO
系统登录成功后返回。回调地址是:www.sso.com?url=www.chezhe2.com。
我们知道之前SSO页面已经与SSO服务端建立了会话,并且因为Cookie
在SSO
这个域名下是共享的,所以此时SSO
系统会判断当前用户已登录。然后就是之前的那一套逻辑了。 此时流程图如下所示:
技术以外的事
老余:不错不错,理解的还可以。你发现这套系统里,做的最多的是什么,有什么技术之外的感悟没。说到这,老余叹了口气。
我:我懂,做的最多的就是验证了,验证真实性、有效性、白名单这些。明明一件很简单的事,最后搞的那么复杂。像现在银行里取钱一样,各种条条框框的限制。我有时候会在想,技术发展、思想变革对于人类文明毋庸置疑是有益的,但是对于我们人类真的是一件好事吗?如果我们人类全是机器人那样的思维是不是会更好点?
老余:我就随便一提,你咋巴拉巴拉了这么多。我只清楚一点,拥有七情六欲的人总是好过没有情感的机器人的。好了,干活去吧。
总结
这一篇内容就到这了,我们聊了下关于单点登录的 CAS 设计思路,其实CAS 往大了讲还能讲很多,可惜我的技术储备还不够,以后有机会补充。如果想理解的更深刻,也可以去看下微信授权流程,应该会有帮助。
最后还顺便提了点技术之外的事,记得有句话叫做:科学的尽头是哲学,我好像开始慢慢理解这句话的意思了。
이 글이 도움이 되셨다면 제 공식 계정 "Rut's Programming Learning Circle"을 주목하시거나 제 블로그 웹사이트에서 코드를 스캔하여 제 블로그 웹사이트를 팔로우하실 수 있습니다 .
저는 Nuggets 소책자 "SkyWalking"의 저자 Che Rut입니다. HR에서 종종 XX Yang Yang으로 조롱하는 인터넷 작업자입니다.