Cookie的secure属性引起单点登录中的循环登录问题
作者:vivo互联网
在实施单点登录(SSO)时,可能会遇到循环登录问题,导致用户无法正常使用系统。本文首先介绍了单点登录的基本概念和实现原理,然后详细分析了循环登录的产生原因,主要是由于Cookie的Secure属性设置不当,在使用HTTP访问时Cookie无法被传递导致的。提出的解决方案包括使用HTTPS进行访问或增加一个新的Cookie参数。此外,还探讨了Cookie端口不隔离性的问题,指出即使是不同端口的服务也会共享同一个Cookie,这增加了处理此类问题的复杂性。整体来看,文章为开发人员提供了处理和预防循环登录问题的有效策略。
一、单点登录简单介绍
1.1 基本概念
一个公司内部可能存在多个系统,如果每一个人在使用不同系统的时候都需要重新登录,那么会做大量系统登录切换、耗费比较多的精力去管理账号和密码,那么有没有办法在一个公司内部的所有系统只需要一次登录验证,后续使用其他系统的时候不用重复登录就可以直接使用呢,这就是单点登录要解决的问题。
单点登录英文全称 Single Sign On(SSO),允许用户一次登录即可访问多个应用程序或系统,无需为每个应用程序或系统分别输入认证凭据,便可在其他所有系统中得到授权,无需再次登录。
1.2 基本实现原理
- 用户登录:用户在任何一个应用程序或系统中进行身份验证,并提供他们的凭据。
- 认证系统验证:该凭据被发送到认证系统进行验证。如果凭据有效,则认证系统会为用户生成数字签名的令牌(如 Token 或 Ticket)。
- 令牌分发:认证系统将令牌返回给应用程序或子系统。
- 应用程序或系统授权:应用程序或系统使用令牌验证用户的身份,并授权其访问相应资源或服务。
- 跨域系统访问:用户可以通过同一令牌访问多个跨域应用程序或系统,而无需重复进行身份验证。
二、循环登录问题
在某一天我们登录一个内部系统时,突然出现了循环登录问题,前端页面不断刷新,提示“重定向次数过多问题”。
打开前端调试功能, 我们会发现确实存在大量重定向请求的问题:
那么平时登录没问题的系统为什么突然间就循环登录呢?并在页面上提示的解决方法“尝试删除您的 Cookie 操作”,按照这个操作以后,确实系统又可以跳转到登录页面正常进行登录了,这又是什么原因?下面我们将逐一分析。
三、从一次正常登录流程说起
上述是一个通用的系统权限管控和单点系统认证的标准流程:
- 用户第一次访问时,在浏览器输入 https://aaa.x.y 回车
- 权限系统进行拦截,判断用户是否登录,这里主要是通过是否有登录信息判断,如果没有登录,权限系统会帮我们跳转到单点登录系统,弹出用户登录页。
- 用户填写用户名、密码,单点登录系统进行认证后,将登录状态写入 SSO 的 session。
- SSO 系统登录完成后会给我们的系统生成一个 Token ,然后跳转到我们的系统,同时将 Token 作为参数传递给我们的系统。
- 我们系统拿到 Token 后,从后台向 SSO 发送请求,验证 Token 是否有效。
- 验证通过后,我们系统将记录顶级域下的 Cookie 信息。
Connection: keep-alive Content-Length: 0 Date: Wed, 25 Oct 2023 08:29:43 GMT Location: http://aaa.x.y/console/login/auth?redirectUrl=http://aaa.x.y/ optrace: xx.xx.xx.xx:80/302 <- - Server: nginx Set-Cookie: token=fakdfajdfdjfdjkfaldfjk'afafjasfasfa; Max-Age=86400; Expires=Thu, 26-Oct-2023 08:29:43 GMT; Domain=x.y; Path=/; HttpOnly
一个公司内部一般情况下只有一个域名,通过二级域名区分不同的系统。比如我们有个域名叫做:x.y ,同时有两个业务系统分别为:app1.x.y 和 app2.x.y。SSO 登录以后,可以将 Cookie 的域设置为顶域,即 x.y ,这样所有子域的系统都可以访问到顶域的 Cookie,实现单点登录功能。
四、循环登录产生的根本原因
那么为什么会不断循环登录呢?
(1)从跳转记录来看,我们发现重新刷新页面以后,重定向到了权限系统,并且 Request Headers 中的 Cookie 信息没有传对应的 Token 信息。
(2)跳转到权限系统过后,再跳转到本系统的时候,已经获取到了对应的 Token 信息,但是在 Set-Cookie 信息的时候,出现了一个警告。
警告的具体内容为:
大致意思是:这次执行 Set-Cookie 操作被阻止了,原因是这个 Cookie 不是通过安全的连接进行传输的,我们这次访问确实使用了 HTTP 进行,本应该通过设置 Secure 属性来覆盖对应的 Cookie。
这里的 Secure 属性是 Cookie 的一个属性,Secure 属性是说如果一个 Cookie 被设置了 Secure = true,那么这个 Cookie 只能用 HTTPS 协议发送给服务器,用 HTTP 协议是不发送的,而我们查看上面标注位置的下一个 Login 请求确实没有传 Cookie 信息,从而继续进行用户是否登录校验,进入死循环过程, 可以看下面的示意图:
五、清除浏览器缓存的底层原理及解决方法
5.1 清除浏览器缓存的底层原理
我们可以看到循环登录以后,会在浏览器页面上提示 xxx.x.y 重定向次数过多,尝试清除 Cookie 信息,那清除 Cookie 信息以后,是不是真的就可以解决这个问题呢,我们尝试着清除浏览器缓存,确实可以解决这个问题,那清除浏览器缓存来解决循环登录问题的底层原理是什么呢,其实质就是将 Cookie 删除,其他域名设置 Cookie 上的 Secure 属性也就一并删除了,从而使用 HTTP 域名进入重新登录流程,可以正常设置 Cookie 信息。
5.2 其他解决办法
方法一:使用 HTTPS 的方式进行访问
现实使用中,我们无法控制其他 HTTPS 访问的具有相同顶级域名的服务不去设置 Cookie 的 Secure 属性,因而我们在后面使用的过程中还是会遇到这个问题,那么有没有一种彻底的解决办法能够避免这个问题再次出现,我们前面已经分析,之所以我们在开始使用 HTTP 能够进行正常访问,然后突然间不能正常访问了,就是因为已经被 HTTPS 设置了的 Cookie 信息是无法被 HTTP 重新设置的,从而拿不到 Cookie 信息。那么就出现了第一种解决办法,使用 HTTPS 的方式进行访问,即使其他服务设置了 Cookie 的 Secure 属性,用 HTTPS 仍然能够成功设置 Cookie 和获取 Cookie。
方法二:在 Cookie 信息中新设置一个 newToken
以上从 HTTP 转为 HTTPS 访问的方法在用户主动找我们反馈时是能够告诉它切换为 HTTPS 访问的,但是如果对于一些没有主动找我们反馈的用户,其实是无法解决,可能丧失这个用户造成用户流失的情况,那么我们在用户不进行切换的情况下是否能够解决这个问题。
同一个公司内部接入的权限系统是一种底层公共能力,为了保证单点登录,其实用户信息的读取都是通过同一个 Cookie 参数(比如叫 Token )读取的,那么在其他域名设置了公共 Cookie 参数的 Secure 属性而影响到 HTTP 登录的时候,我们可以给服务新增加一个 Cookie 参数 newToken 去解决。
六、扩展: Cookie 的端口不隔离性
本文所阐述的问题,出现的背景是有两个基本前提的:一是为了保证单点登录,两个域名属于同一个顶级域名,权限系统中关于用户信息的校验都是通过同一个 Cookie 属性去读取的;第二个是 HTTPS 设置了顶级域名的 Cookie 信息的 Secure 属性,然后使用 HTTP 访问会导致循环登录。有些开发者可能会有这样一个疑问,那就是 HTTPS 我们一般开通的端口是 443 , HTTP 我们一般开通的端口是 8080 ,为啥不从端口上进行区分同一个 Cookie 属性从而避免干扰呢?
这个在 Cookie 规范(RFC 6265)中有所描述,那就是 Cookie 不提供通过端口进行隔离的,也就是说如果一个 Cookie 可以被一台服务器上的运行在某一个端口上的一个服务所读取,那么也可以被这台服务器上运行在另外一个端口上的服务所读取;如果一个 Cookie 可以被一台服务器上的运行在某一个端口上的一个服务所写入,那么也可以被这台服务器上运行在另外一个端口上的服务所写入。
七、总结
单点登录作为公共组件,在各个公司内部被各个系统所广泛使用,但是在使用过程中我们会遇到各种各样的问题,其中循环登录问题就是一个比较经典的问题。本文主要分析单点登录和权限系统设计的基本原理,然后结合实际案例来分析循环登录的原因,并给出具体的解决办法。
本文从实际开发过程中遇到的循环登录问题入手,分析了由于设置 Secure 属性导致使用 HTTP 访问网页无法保存 Cookie 信息从而导致循环登录的根本原因,也给出了其他两个解决此种问题的方案,对于其他开发人员解决权限系统循环登录问题具有一定的借鉴意义。
到此这篇关于Cookie的secure属性引起单点登录中的循环登录问题的文章就介绍到这了,更多相关单点登录中的循环登录内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!