首页天道酬勤单点登录与oauth2(jwt和shiro单点登录)

单点登录与oauth2(jwt和shiro单点登录)

admin 12-01 21:45 293次浏览

单点登录是我比较喜欢的技术解决方案。一方面可以提高产品使用的便利性;另一方面,它分离了每个应用程序所需的登录服务,这对性能和工作负载都有好处。

自从我上次研究了JWT如何应用于会话管理,以及CAS这种流行的单点登录框架在之前的项目中被使用之后,我就一直在想如何一起使用JWT单点登录,尽可能地将两种技术的优势融合到项目中。本文介绍了我从CAS想到的单点登录的实现方案。

00-1010事实上,CAS是一个非常好且强大的解决方案。它的最新版本集成了JWT,所以如果你不想开发自己的单点登录服务,可以考虑使用CAS。然而,我认为当我们在做一个项目时,也许我们一开始并不需要这么强大的产品。CAS提供的登录表单很多,我们只需要申请其中一个即可。

而且,它是一个强大的框架,所以它会很复杂,很容易使用。但是如果遇到一些特殊的需求,比如我们想把微信登录添加到CAS中,就需要对它的原理和API有更深入的了解。综合考虑,找出CAS的原理,自己实现一个基本的SSO服务更让人放心。

本文的内容需要对JWT和SSO有一个基本的了解。你可以从这两篇文章中了解到JWT的目的:

http://www.cnblogs.com/lyzg/p/6067766.html

http://www.cnblogs.com/lyzg/p/6028341.html

您还可以从以下材料中了解单点登录:

https://baike.baidu.com/item/SSO/3451380?阿拉丁

00-1010本文主要通过时序图的方式介绍JWT SSO的实现原理。具体的技术实现还没有,但是激情煎蛋了解了这个方案的原理之后,你会觉得最终的实现并不是特别复杂,可以用任何平台语言实现。

下面的时序图模拟了三种服务,即CAS、系统A和系统B,它们分别部署在cas.com、systemA.com和systemB.com。CAS服务用于管理单点登录会话;系统A和系统B代表实际的业务系统。我将从五个场景来解释这个单点登录方案的实现细节。先看第一个。

场景一:用户发起对业务系统的第一次访问,假设他首先访问了系统A的某个/页面的页面,他成功访问该页面的过程如下:

点击放大图片,下同。

在这个过程中,我认为理解的要点是:

它使用两个cookie(jwt和sid)和三个重定向来完成会话的创建和交付。Jwt cookie是在systemA.com的域中编写的,所以每次您重定向到systemA.com时,只要jwt cookie存在,它就会随身携带。的sid cookie是在cas.com的域中编写的,因此每次您重定向到cas.com时,只要sid cookie存在,它就会随身携带。验证jwt时,如何知道当前用户已经创建了sso会话?因为之前创建的sso session的session id存储在jwt的有效载荷中,当cas获取jwt时,相当于获取session id,然后使用这个session id来判断是否有对应的session对象。还需要注意的是,CAS服务中的会话属于服务器创建的对象,因此需要考虑会话id的唯一性和会话的共享性(如果CAS采用集群部署)。会话id的唯一性可以简单地通过在用户名密码和哈希算法(如md5)中添加随机数来处理。会话共享可以由memcached或redis(一种支持集群部署的特殊缓存服务器)来管理会话。

由于服务器会话具有生命周期的特点,到期需要自动销毁,所以不要自己写会话的管理,以免造成其他问题,直接去github找开源缓存管理中间件处理就可以了。存储会话对象时,只需使用会话id作为键,会话对象本身作为值,并将其存储在缓存中。除了会话id,会话对象还可以存储登录后获取的用户信息等业务数据,方便业务系统调用时从会话中返回会话数据。

场景二:用户登录后,继续访问系统A的其他页面,如some/page2,其处理过程如下:

从这一步中,我们可以看到,即使在登录之后,我们也应该检查jwt的有效性以及每次与CAS的会话的有效性。事实上,jwt的有效性也可以在业务系统中处理,但是会话的有效性只能由CAS来完成。当CAS获得jwt中的会话id时,可以去会话缓存服务器验证会话id对应的会话对象是否存在,这意味着会话已经被销毁(退出)。

场景三:用户登录了系统A之后,再去访问其他系统如系统B的资源,比如系统B的some/page,它最终能访问到系统B的some/page的流程是:

这个过程的关键在于第一次重定向的时候,它会把sid这个cookie带回给CAS服务器,所以CAS服务器能够判断出会话是否已经建立,如果已经建立就跳过登录页的逻辑。

场景四:用户继续访问系统B的其它资源,如系统B的some/page2:

这个场景的逻辑跟场景二完全一致。

场景五:退出登录,假如它从系统B发起退出,最终的流程是:

最重要的是要清除sid的cookie,jwt的cookie可能业务系统都有创建,所以不可能在退出的时候还挨个去清除那些系统的cookie,只要sid一清除,那么即使那些jwt的cookie在下次访问的时候还会被传递到业务系统的服务端,由于jwt里面的sid已经无效,所以最后还是会被重定向到CAS登录页进行处理。

方案总结

以上方案两个关键的前提:

整个会话管理其实还是基于服务端的session来做的,只不过这个session只存在于CAS服务里面;CAS之所以信任业务系统的jwt,是因为这个jwt是CAS签发的,理论上只要认证通过,就可以认为这个jwt是合法的。

jwt本身是不可伪造,不可篡改的,但是不代表非法用户冒充正常用法发起请求,所以常规的几个安全策略在实际项目中都应该使用:

使用https使用http-only的cookie,针对sid和jwt管理好密钥防范CSRF攻击。

尤其是CSRF攻击形式,很多都是钻代码的漏洞发生的,所以一旦出现CSRF漏洞,并且被人利用,那么别人就能用获得的jwt,冒充正常用户访问所有业务系统,这个安全问题的后果还是很严重的。考虑到这一点,为了在即使有漏洞的情况将损害减至最小,可以在jwt里面加入一个系统标识,添加一个验证,只有传过来的jwt内的系统标识与发起jwt验证请求的服务一致的情况下,才允许验证通过。这样的话,一个非法用户拿到某个系统的jwt,就不能用来访问其它业务系统了。

在业务系统跟CAS发起attach/validate请求的时候,也可以在CAS端做些处理,因为这个请求,在一次SSO过程中,一个系统只应该发一次,所以只要之前已经给这个系统签发过jwt了,那么后续 同一系统的attach/validate请求都可以忽略掉。

总的来说,这个方案的好处有:

完全分布式,跨平台,CAS以及业务系统均可采用不同的语言来开发;业务系统如系统A和系统B,可实现服务端无状态假如是自己来实现,那么可以轻易的在CAS里面集成用户注册服务以及第三方登录服务,如微信登录等。

它的缺陷是:

第一次登录某个系统,需要三次重定向(不过可以优化成两次);登录后的后续请求,每次都需要跟CAS进行会话验证,所以CAS的性能负载会比较大登陆后的后续请求,每次都跟CAS交互,也会增加请求响应时间,影响用户体验。

本文小结

本文从理论层面介绍了结合jwt来实现SSO的方案原理,希望它能帮助一些朋友更好的理解SSO以及它的实现方法。本文方案参考自CAS的实现流程,你可以从下面这个资料了解CAS的单点登录实现过程:

https://apereo.github.io/cas/4.1.x/protocol/CAS-Protocol.html

它的流程跟我这个差别不是特别大,但是从清晰层面来说,我写的还是要更明了一些,所以对比起来阅读,可能理解会更透彻些。

另外,这个方案考虑地不一定很全面,所以要是您发现了其中的问题,还请您帮忙指正,非常感谢。

链接:cnblogs.com/lyzg/p/6132801.html

回复“资源”,领取 练手源码,视频教程,微服务、并发,数据可调优等,搜索【Java知音】

javascript尾递归优化Kafka消息队列 产品介绍 UKafkaHDFS shell操作超帅!无人机巡检上海1.3万座玻璃幕墙的背后Java怎么利用多线程模拟银行系统存钱问题Android数据存储方式是什么C++构造析构赋值运算函数怎么应用如何彻底卸载VMware虚拟机
前端数据可视化是什么意思(前端常用api) java小白教程(java小白)
相关内容