单点登录的三种方式

前言

在B/S系统中,登录功能通常都是基于Cookie 来实现的。当用户登录成功后,一般会将登录状态记录到Session中,或者是给用户签发一个 Token,无论哪一种方式,都需要在客户端保存一些信息(Session ID或Token),并要求客户端在之后的每次请求中携带它们。在这样的场景下,使用Cookie无疑是最方便的,因此我们一般都会将Session的ID或 Token保存到Cookie中,当服务端收到请求后,通过验证Cookie中的信息来判断用户是否登录。

单点登录(Single Sign On,SSO)是指在同一帐号平台下的多个应用系统中,用户只需登录一次,即可访问所有相互信任的应用系统。举例来说,百度贴吧和百度地图是百度公司旗下的两个不同的应用系统,如果用户在百度贴吧登录过之后,当他访问百度地图时无需再次登录,那么就说明百度贴吧和百度地图之间实现了单点登录。单点登录的本质就是在多个应用系统中共享登录状态。如果用户的登录状态是记录在Session 中的,要实现共享登录状态,就要先共享Session,比如可以将 Session序列化到Redis中,让多个应用系统共享同一个Redis,直接读取 Redis来获取 Session。当然仅此是不够的,因为不同的应用系统有着不同的域名,尽管Session 共享了,但是由于Session ID是往往保存在浏览器Cookie中的,因此存在作用或的限制,无法跨域名传递,也就是说当用户在app1.com中登录后,SessionID仅在浏览器访问app1.com时才会自动在请求头中携带,而当浏览器访问app2.com时,Session ID是不会被带过去的。实现单点登录的关键在于,如何让 Session ID(或Token)在多个域中共享。

实现方式一:父域 Cookie

在将具体实现之前,我们先来聊一聊Cookie的作用域。Cookie 的作用域由 domain属性和path 属性共同决定。domain属性的有效值为当前域或其父域的域名/IP地址,在Tomcat中,domain属性默认为当前域的域名/IP地址。path属性的有效值是以“/”开头的路径,在Tomcat 中,path属性默认为当前Web应用的上下文路径。如果将Cookie的 domain属性设置为当前域的父域,那么就认为它是父域Cookie。Cookie有一个特点,即父域中的Cookie被子域所共享,换言之,子域会自动力继承父域中的Cookie。利用Cookie的这个特点,不难想到,将SessionID(或Token)保存到父域中不就行了。没错,我们只需要将Cook ie 的 domain属性设置为父域的域名(主域名),同时将Cookie的path 属性设置为根路径,这样所有的子域应用就都可以访问到这个Cookie了了。不过这要求应用系统的域名需建立在一个共同的主域名之下,如tieba.baidu.com和map.baidu.com,它们都建立在baidu.com这个主域名之下,那么它们就可以通过这种方式来实现单点登录。
总结:此种实现方式比较简单,但不支持跨主域名。

实现方式二:认证中心

我们可以部署一个认证中心,认证中心就是一个专门负责处理登录请求的独立的 Web服务。用户统一在认证中心进行登录,登录成功后,认证中心记录用户的登录状态,并将Token写入Cookie。(注意这个 Cookie是认证中心的,应用系统是访问不到的)应用系统检查当前请求有没有 Token,如果没有,说明用户在当前系统中尚未登录,那么就将页面面跳转至认证中心。由于这个操作会将认证中心的Cookie自动带过去,因此,认证中心能够根据Cookie知道用户是否已经登录过了。如果认证中心发现用户尚未登录,则返回登录页面,等待用户登录,如果发现用户已经登录过了,就不会让用户再次登录了,而是会跳转回目标URL,并在跳转前生成一个Token,拼接在目标URL 的后面,回传给目标应用系统。应用系统拿到Token之后,还需要向认证中心确认下Token的合法性,防止用户伪造。确认无误后,应用系统记录用户的登录状态,并将 Token写入Cookie,然后给本次访问放行。(注意这个Cookie是当前应用系统的,其他应用系统是访问不到的。)当用户再次访问当前应用系统时,就会自动带上这个Token,应用系统验证Token发现用户已登录,于是就不会有认证中心什么事了。

实现方式三:LocalStorage 跨域

前面我们说实现单点登录的关键在于,如何让 Session ID(或Token)在多个域中共享。父域Cookie 确实是一种不错的解决方案,但是不支持跨域。那么有没有什么奇淫技巧能够让Cookie 跨域传递呢?很遗憾,浏览器对Cookie的跨域限制越来越严格。Chrome 浏览器还给Cookie新增了一个SameSite属性,此举几乎禁止了一切跨域请求的Cookie传递(超链接除外),并且只有当使用HTTPs协议时,才有可能被允许在AJAX跨域请求中接受服务器传来的Cookie。不过,在前后端分离的情况下,完全可以不使用Cookie,我们可以选择将Session ID(或Token)保存到浏览器的 LocalStorage中,让前端在每次向后端发送请求时,主动将LocalStorage的数据传递给服务端。这些都是由前端来控制的,后端需要做的仅仅是在用户登录成功后,将Session ID(或To oken)放在响应体中传递给前端。在这样的场景下,单点登录完全可以在前端实现。前端拿到 Session ID(或Token)后,除了将它写入自己的 LocalStorage中之外,还可以通过特殊手段将它写入多个其他域下的LocalStorage 中。关键代码如下:

在这里插入图片描述
前端通过iframe+postMessage()方式,将同一份 Token写入到了多个域下的LocalStorage中,前端每次在向后端发送请求之前,都会主动从LocalStorage 中读取 Token并在请求中携带, 这样就实现了同一份Token 被多个域所共享。
总结:此种实现方式完全由前端控制,几乎不需要后端参与

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/498626.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java程序设计】【C00317】基于Springboot的智慧社区居家养老健康管理系统(有论文)

基于Springboot的智慧社区居家养老健康管理系统(有论文) 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的智慧社区居家养老健康管理系统设计与实现,本系统有管理员、社区工作人员、医生以及家属四种角色权限 管…

嵌入式学习第二十二天!(线程间通信)

线程间通信: 线程间通信,通过利用全局变量,来实现通信,但是在通信过程中使用这些变量可能会导致资源竞争,那么就需要使用到互斥锁和信息量,辅助我们实现线程的通信。 1. 线程分离属性: 线程结束…

简单版 git快速上手使用 clone项目 新建/切换分支 提交修改

Git是一个广泛使用的版本控制系统,允许多个用户跟踪文件的更改,并协作开发项目。 首先确定自己电脑已经安装了git,具体安装步骤请查找教程,应该不难。 以windows电脑为例,安装完后在搜索栏搜索git会出现 先解释一下这…

J1—Vivado调试技巧VIO IP

1.简介 VIO(Virtual Input/Output)IP核是一种用于FPGA设计的IP核,它可以模拟输入/输出设备的功能,如键盘、鼠标、显示器等。VIO IP核可以在FPGA设计中用于调试和验证,帮助工程师快速定位问题并进行调试。如图所示&…

学习阶段单片机买esp32还是stm32?

学习阶段单片机买esp32还是stm32? 在开始前我有一些资料,是我根据网友给的问题精心整理了一份「stm32的资料从专业入门到高级教程」, 点个关注在评论区回复“888”之后私信回复“888”,全部无偿共享给大家!!&#xf…

放着奥威-用友BI方案不用?糊涂!

放着奥威-用友BI方案不用,自己在那死磕数据可视化报表开发、数据分析报表开发,白白投了大量的人力物力进去,还得不到好效果,比百忙一场还要亏。 奥威-用友BI方案究竟有多优秀? 1、分析快,报表制作快 半个…

Socket网络编程(三)——TCP快速入门

目录 概述TCP连接可靠性1. 三次握手过程2. 四次挥手过程3. 为什么挥手需要四次? 传输可靠性TCP核心APITCP传输初始化配置&建立连接客户端创建Socket建立连接服务端创建ServerSocket监听连接ServerSocket 和 Socket的关系 Socket基本数据类型传输客户端数据传输服…

web前端-html自定义列表

html 自定义列表 <!--有序列表 应用范围&#xff1a;试卷、问答--> <ol><li>Java</li><li>C</li><li>Python</li><li>C</li><li>VB</li> </ol><br><!--无序列表 应用范围&#xff1a…

渗透测试靶场环境搭建

1.DVWA靶场 DVWA&#xff08;Damn Vulnerable Web Application&#xff09;是一个用来进行安全脆弱性鉴定的PHP/MySQL Web应用&#xff0c;包含了OWASP TOP10的所有攻击漏洞的练习环境&#xff0c;旨在为安全专业人员测试自己的专业技能和工具提供合法的环境&#xff0c;同时…

html2canvas + JsPDF.js 导出pdf分页时的问题

问题描述 前一段时间 实现了html2canvas jspdf.js 导出pdf的功能 项目当时没有测试做完就先搁置 最近项目要上线发现分页时问题 这篇文章记录一下之前的bug import html2canvas from html2canvas; import JsPDF from jspdf export function savePdf(el, title) {html2canva…

微信小程序真机调试:连接局域网失败ws://********:8001/失败,已切换回广域网模式的解决方式

这个问题大多数是由于系统上安装了虚拟网卡造成&#xff0c;只要禁用虚拟网卡即可查询方式&#xff1a;windx - 选择设备管理器 - 查看网络适配器&#xff0c;找到虚拟网卡禁用 重新勾选局域网模式进行调试即可

开发知识点-Python-conda

Python-conda https://conda.io/miniconda.html conda search python conda env list conda deactivate conda activate python11 conda 是一个流行的开源包管理系统&#xff0c;它支持多种 Python 版本。 使用 conda 来创建和管理不同的 Python 环境&#xff0c;并在这些环…