一、实记基本信息介绍
1、实记前言
此文章主要记录我是如何处理以及解决在通过cas 单点登录把我们的系统集成到已有平台过程中遇到的一些问题以及对应问题的处理方法,因为每一个研发环境以及生产环境都不同,所以本文所说不免有局限之处,欢迎大家一起学习讨论。
2、项目背景以及开发环境简单介绍
我们开发环境大致情况如下: Win10、JDK1.8,mysql、达梦,SpringBoot2.2.13、SpringSecurity、Vue、Nginx、Maven、Gitee、Fiddle(抓包分析)。
项目背景:客户既有的等待升级的P平台(用户、权限等已经具备),如无特殊说明,下文所有的p都是指P平台。p升级内容的一部分功能是原有的p平台团队负责,此处称作A系统,我们负责p平台升级的另一部分内容,称作B系统。因为整个系统的入口在p平台,A项目也是基于p平台研发的,所以最后,按照客户的需求和两个团队的商定,最终的方案是A系统通过Iframe嵌入B系统的页面,进而实现整个系统的完整。但是这一方案也为后面的项目推进埋下了不少问题。另外为了解决用户不用重复登录登出的问题引入了CAS单点登录以及认证,下文会有详细说明。
3、生产环境介绍(内网)
p平台:国产凝思、达梦,A系统:国产凝思、达梦,同时都部署在110服务器
B系统:应用服务器:国产凝思,达梦,部署在120,数据库服务器:centos8,mysql,部署在108。
如下图:
4、客户要求
- 同一个系统:(客户等到我们都开发的差不多了才提出这个需求。。。)B系统独立开发,并且与p平台和A系统部署在不同的服务器上面,但是整个系统作为一个整体对外提供服务,并且保证系统必要的安全性。用户在p平台登陆以后,继续访问B系统不能重复登录,其次用户在p系统登出以后,B系统同时保证用户登出。这样导致了最后cas的引入。(。。。。无处无数个cnm。。。。。。送给老是变动需求的kh。。。。)
- p、A、B三者之间用户和权限的一致性:根据4.1客户的要求还有现有的环境条件,我们去实现客户的需求,肯定会遇到一些问题如下:(1)A与p本身部署在同一台服务器,所以A系统感知用户信息的变化是实时的,A系统与p平台使用同一个数据库,所以A系统不需要额外处理。(2)要保证B系统不能发生数据以及功能的混乱 A系统与p平台使用同一个数据库,这样p平台有用户变动或者是权限变动时A系统能实时感知到,。但是B系统因为有天然的物理隔离所以并不具备实时感知用户信息数据变化的能力,,加上前期客户说A、B 两个系统是单独的,分开的,所以各自处理自己系统的用户和权限(A系统直接用p的就行,不用开发),这样初期我们自己研发了B系统的用户管理还有权限管理。所以当后来客户提出A、B两套系统要作为整体对外服务的时候,我们不得废弃了自己研发的用户管理和权限管理,更何况我们B系统存在流程处理这样对用户数据和权限关联性比较强的业务。。。。不说了,我赶紧擦擦汗。。。。。。此处省略了 ‘’cnm ‘’ 的整数倍个字。。。不带这样搞的呀。。。。流泪啊。。。 (3)如果p或者A发生了用户信息维护,那么不能让用户再去B系统维护一次,毕竟这系统对用户来讲是同一个系统,如果还需要在好几个地方维护那说不过去。擦。。。。。
5、我们研发的最终目标
- 拿到最新用户数据: 因为p平台与我们的B系统存在物理隔离。所以如果要实现客户的需求只需要在使用用户数据的时候能获取到最新的用户数据就行。这里有如下几种方案:(1)实时同步 但是如果采取实时同步的话有点浪费资源,因为不可能时时刻刻都有用户数据变动或者权限变动。最后被放弃(2) 我们B系统提供接口,p当有用户数据变动的时候推送变动的用户数据个给我们,这样我们可以在我们系统维护一份跟P平台相同的用户和权限数据的副本,只要p有变动 我们随之跟着更新就行,但是因为公司层面关系,我们没有占得先机,导致我们的处境有点被动,另外p平台体量也确实很大,修改的话怕是会影响面积太大。最后也被放弃(3)定时同步 如果采取定时同步的话,那就存在一定的问题,有可能新来了一个用户,管理员已经给新用户分配了权限,此时用户去处理业务了,但是因为我们本地的用户数据副本没有跟p保持一致。这样新用户就没办法进行操作B系统的业务了。最后该方案也被放弃。(4)让p平台开放数据库权限,B系统配置多数据源,读取p的数据库,貌似该方案是最可行的办法。但是也有问题,就是用户数据拿到了,但是下该如何保证同步的登录登出呢?请看5.2。
- 实时感知用户在p系统的登录和登出操作: 要感知到用户在p平台的行为只是靠我们B系统确实不太好处理。所以我们与p研发团队进行沟通,商量在双方都尽量改动最小的情况下实现客户的需求。(1) 页面调用时添加用户信息参数在url后面,该种方法貌似是可行的。访问我们的时候传递一个用户信息,我们倒是可以拿到用户信息了,也能进行后面的正常的业务操作,但是用户访问到我们B系统的的页面的时候,B页面处于打开状态,如果用户此时又打开了p或者A的页面,然后用户不在进行任何操作,直到session过期,用户又回来继续操作。此时访问A或者p,因为A系统或者p平台能知道用户session已经过期了,会自动弹出一个登陆页面,或者提示用户登录过期了。但是我们B系统的页面此时依旧能进行操作,擦。。。。。那该如何把用户的登录状态信息拿到呢,,,,,第一p平台不能修改太多,第二我们也不想修改太多,第三传递一个标记过来,但是我们如何解析呢。如何区分不同的用户呢,此处一万个如何如何如何,3万个这个该怎么解决呢。那个该怎么解决呢。。。。,第四把p平台的cookie 传递过来,但是cookie是加密的,我们如何解密呢,我们对于p平台的加密解密细节并不知道,此时感觉这个问题无解了。。。。。。(2)经过反复的讨论和考虑,没有找到合适的并且感觉比较可靠的方案,干脆实在不行可以加一个服务,单独处理p、A、B三者的登录登出。经过沟通和协商,并从p平台的大佬哪里了解到,p平台的团队整好有配套的单点解决方案,并且已经在其他客户哪里有过实践。。。。。擦,,这问题不就可以解决了么。。。。。。哈哈。。。老高兴了。。。。估计做梦都笑了。。。。。但是这才是噩梦的开始。为啥说是噩梦呢,其实还是各种小的因素综合作用的结果。各种小的问题积聚起来了,形成了一个大的问题。。。。看官,,请您往下看。。。。。
二、解决问题的过程
- 最终方案 因为通过最终的讨论和考虑,双方确定最后的解决方案:(1)p平台开放数据库权限给B系统,B系统添加多数据源实现用户数据的读取(2)搭建独立的单点认证服务cas-server,p平台集成cas-client(A基于p开发,不用单独处理),B系统集成cas-client。
- **开干 ** 既然选定了方案,那就开始干吧,,,,,开撸。。。。。此处详细介绍一下我们的系统。我们系统采用的是前后端分离开发,并且前后端分离部署,通过Nginx对外发布。本地开发环境搭建单点认证服务cas-tomcat,项目后台集成casClient,本地搭建与p平台对应的用户数据的数据库,达梦数据库,方便我们访问,也方便cas-tomcat访问,同时我们还有自己的mysql数据库存储业务数据,另外本地安装nginx,安装nginx以后 ,后来也安装了openssl ,尽量做到与生产环境一致。
- 开发环境遇到的问题 这几个比较小的问题是本地开发环境遇到的(1)集成cas单点登录 遇到casClient相关的jar包不加载(2)jar包加载了但是casClient客户端拦截不到用户的请求 (3)拦截到请求了,终于进入到登录环节了,但是输入对应的用户名以及密码以后后台 报票根错误。(4)不报票根错误了,但是登录成功以后到后应该跳转到我们系统的对应页面,但是浏览器直接显示了一段被它自己识别为普通字符串的html代码(5)不显示字符串了,艾玛。。。。。终于看到我们系统的的页面了。。以为就此结束。
- 内测环境遇到的问题 当看到我们的页面以后以为万事大吉了,我们开始按部就班的在本地进行开发。同事也就都按部就班的干活,问题终于有解了。等到开发了一个功能以后,心想保险起见,该集成一下部署到测试环境测试一下了。这一试不要紧,又有新的问题出现了。在我们本地开发环境DEV测试都没有问题,但是部署到内侧环境SIT以后出现报错。(1)用户登录成功以后,点击A系统页面对应的按钮,正常的话应该是在他们的当前的页面中弹出一个弹窗,这个弹窗通过iframe 展示我们的页面,但是实际的现象确是浏览器直接打开了一个新的窗口,来展示我们的页面,这样导致了A系统的一个自动处置流程被迫中断(2)点击A系统页面对应的按钮,在当前页面通过弹窗显示我们的页面以后,我们页面回调用后台接口,但是当时的现象是刨去没有以正确的方式打开我们的页面以外,页面调用我们后台接口时也报错。(3)当解决完了让我们的页面在iframe里可以正确显示以后,新的问题又出现了,本应该嵌套显示的是我们对应的业务的页面,但是此时是显示的登录页面。也就是,用户已经登陆了一次了,应该直接跳转到我们业务页面,但是不知什么原因又被casClient拦截了,直接认定当前用户没有登录,跳转到了登录页。(4)解决好了跳转登录页面以后以后本以为问题得到了解决,但是现实情况很打击人,本应该显示我们页面的地方死活不显示我们的页面,后来终于发现是浏览器的安全限制问题,如果用iframe 嵌套第三方页面,通过http请求方式访问第三方系统的时候,浏览器会禁止携带第三方的cookie去请求对应的第三方系统,也就是所谓的cookie丢失(5)为了解决iframe cookie丢失问题,我们采取了https请求方式。结果问题依旧没有得到解决。此时陷入无解的境地。各位看官如果我这篇啰嗦的文章您都能看到这里了请您继续往下看,
**
**