面试官:说一下单点登录的几种实现方式

2023-11-05

Java面试笔试面经、Java技术每天学习一点

Java面试

关注不迷路

作者:张永恒

来源:https://www.cnblogs.com/yonghengzh/p/13712729.html

在 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中登录后,Session ID仅在浏览器访问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 的这个特点,不难想到,将Session ID(或 Token)保存到父域中不就行了.没错,我们只需要将 Cookie的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 发现用户已登录,于是就不会有认证中心什么事了。

这里顺便介绍两款认证中心的开源实现:

1.Apereo CAS 是一个企业级单点登录系统,其中 CAS 的意思是”Central Authentication Service“.它最初是耶鲁大学实验室的项目,后来转让给了 JASIG 组织,项目更名为 JASIG CAS,后来该组织并入了Apereo 基金会,项目也随之更名为 Apereo CAS。

2.XXL-SSO 是一个简易的单点登录系统,由大众点评工程师许雪里个人开发,代码比较简单,没有做安全控制,因而不推荐直接应用在项目中,这里列出来仅供参考。

总结:此种实现方式相对复杂,支持跨域,扩展性好,是单点登录的标准做法。

「实现方式三:LocalStorage 跨域」

前面,我们说实现单点登录的关键在于,如何让Session ID(或 Token)在多个域中共享。

父域 Cookie 确实是一种不错的解决方案,但是不支持跨域.那么有没有什么奇淫技巧能够让Cookie跨域传递呢?

很遗憾,浏览器对Cookie的跨域限制越来越严格.Chrome 浏览器还给Cookie新增了一个 SameSite 属性,此举几乎禁止了一切跨域请求的Cookie传递(超链接除外),并且只有当使用https协议时,才有可能被允许在 AJAX 跨域请求中接受服务器传来Cookie。

不过,在前后端分离的情况下,完全可以不使用Cookie,我们可以选择将 Session ID(或 Token)保存到浏览器的 LocalStorage 中,让前端在每次向后端发送请求时,主动将 LocalStorage 的数据传递给服务端.这些都是由前端来控制的,后端需要做的仅仅是在用户登录成功后,将 Session ID(或 Token)放在响应体中传递给前端。

在这样的场景下,单点登录完全可以在前端实现,前端拿到 Session ID(或 Token)后,除了将它写入自己的 LocalStorage 中之外还可以通过特殊手段将它写入多个其他域下的LocalStorage 中。

关键代码如下:

// 获取 token  
var token = result.data.token;  
  
// 动态创建一个不可见的iframe,在iframe中加载一个跨域HTML  
var iframe = document.createElement("iframe");  
iframe.src = "http://app1.com/localstorage.html";  
document.body.append(iframe);  
// 使用postMessage()方法将token传递给iframe  
setTimeout(function () {  
    iframe.contentWindow.postMessage(token, "http://app1.com");  
}, 4000);  
setTimeout(function () {  
    iframe.remove();  
}, 6000);  
  
// 在这个iframe所加载的HTML中绑定一个事件监听器,当事件被触发时,把接收到的token数据写入localStorage  
window.addEventListener('message', function (event) {  
    localStorage.setItem('token', event.data)  
}, false);  
 
 
 

前端通过 iframe+postMessage() 方式,将同一份 Token 写入到了多个域下的 LocalStorage 中,前端每次在向后端发送请求之前,都会主动从 LocalStorage 中读取 Token 并在请求中携带,这样就实现了同一份 Token 被多个域所共享。

总结:此种实现方式完全由前端控制,几乎不需要后端参与,同样支持跨域。

「补充:域名分级」

从专业的角度来说(根据《计算机网络》中的定义),.com、.cn 为一级域名(也称顶级域名),.com.cn、baidu.com 为二级域名,sina.com.cn、tieba.baidu.com 为三级域名,以此类推,N 级域名就是 N-1 级域名的直接子域名。

从使用者的角度来说,一般把可支持独立备案的主域名称作一级域名,如 baidu.com、sina.com.cn 皆可称作一级域名,在主域名下建立的直接子域名称作二级域名,如 tieba.baidu.com 为二级域名。

为了避免歧义,本人将使用"主域名"替代"一级域名"的说法

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

面试官:说一下单点登录的几种实现方式 的相关文章

  • 响应式图像 - srcset 和尺寸属性 - 如何正确使用两者:基于设备像素比和基于视口的选择一起?

    到目前为止 我经常读到这个问题 并且它也发生在我自己的项目中 这里介绍一下我到目前为止所发现的关于 srcset 和 size 属性的内容 关于如何使用有两种不同的可能性srcset 属性 来源 w3c http w3c github io
  • 无法展开 RemoteViews - 错误通知

    最近 我收到越来越多的用户收到 RemoteServiceException 错误的报告 我每次给出的堆栈跟踪如下 android app RemoteServiceException Bad notification posted fro
  • 加速代码 - 3D 数组

    我正在尝试提高我编写的一些代码的速度 我想知道从 3d 整数数组访问数据的效率如何 我有一个数组 int cube new int 10 10 10 我用价值观填充其中 然后我访问这些值数千次 我想知道 由于理论上所有 3d 数组都存储在内
  • Spark 1.3.1 上的 Apache Phoenix(4.3.1 和 4.4.0-HBase-0.98)ClassNotFoundException

    我正在尝试通过 Spark 连接到 Phoenix 并且在通过 JDBC 驱动程序打开连接时不断收到以下异常 为简洁起见 下面是完整的堆栈跟踪 Caused by java lang ClassNotFoundException org a
  • Spring Data JPA 应用排序、分页以及 where 子句

    我目前正在使用 Spring JPA 并利用此处所述的排序和分页 如何通过Spring data JPA通过排序和可分页查询数据 https stackoverflow com questions 10527124 how to query
  • 无法解析插件 Java Spring

    我正在使用 IntelliJ IDEA 并且我尝试通过 maven 安装依赖项 但它给了我这些错误 Cannot resolve plugin org apache maven plugins maven clean plugin 3 0
  • 禁止的软件包名称:java

    我尝试从数据库名称为 jaane 用户名 Hello 和密码 hello 获取数据 错误 java lang SecurityException Prohibited package name java at java lang Class
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • 如何将 pfx 文件转换为 jks,然后通过使用 wsdl 生成的类来使用它来签署传出的肥皂请求

    我正在寻找一个代码示例 该示例演示如何使用 PFX 证书通过 SSL 访问安全 Web 服务 我有证书及其密码 我首先使用下面提到的命令创建一个 KeyStore 实例 keytool importkeystore destkeystore
  • 网站的主体和元素固定在 980px 宽度上,不会缩小

    我试图在 Rails 应用程序顶部启动前端 仅 HTML CSS 页面 但在使用 320px 视口时遇到问题 有些元素不会按比例缩小 我不明白为什么 我已经完成了检查元素 为各种元素提供了max width 100 and or width
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • 刷新页面时保存用户的选择

    我目前有一个页面显示不同团队的数据 我有一些数据 用户可以单击使其处于 打开 或 关闭 状态 并为每个数据显示不同的图标 它基本上就像一个清单 只是没有物理复选框 我想记住哪些 复选框 已被选中 即使在用户刷新页面或关闭浏览器并稍后返回之后
  • PHP session_regenerate_id 和黑莓浏览器

    问候 我正在开发一个登录系统 并陷入了黑莓浏览器身份验证的困境 他们似乎对 PHP 的 session regenerate id 有问题 有人可以建议替代方案吗 以下是身份验证和登录脚本 UPDATE看来会话一般都不起作用 拿出 sess
  • Java执行器服务线程池[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 如果我使用 Executor 框架在
  • Google App Engine 如何预编译 Java?

    App Engine 对应用程序的 Java 字节码使用 预编译 过程 以增强应用程序在 Java 运行时环境中的性能 预编译代码的功能与原始字节码相同 有没有详细的信息这是做什么的 我在一个中找到了这个谷歌群组消息 http groups
  • 如何创建适合屏幕宽度的等宽/高框? [复制]

    这个问题在这里已经有答案了 我正在尝试建立一个网站 其中有很多宽度和高度相等的框 例如 我有一个页面 其中并排有两个相同大小的框 简单的解决方案是将宽度和高度设置为 50vw 这在出现滚动条之前效果很好 我已经用谷歌搜索了几个小时 但无法理
  • 表格行未扩展到全宽

    我有一个表格 当我将表格的宽度设置为 100 并将表格行的宽度设置为 100 时 没有任何反应或宽度发生变化 Table Normal position relative display block margin 10px auto pad
  • 玩!框架:运行“h2-browser”可以运行,但网页不可用

    当我运行命令时activator h2 browser它会使用以下 url 打开浏览器 192 168 1 17 8082 但我得到 使用 Chrome 此网页无法使用 奇怪的是它以前确实有效 从那时起我唯一改变的是JAVA OPTS以启用
  • Firebase 添加新节点

    如何将这些节点放入用户节点中 并创建另一个节点来存储帖子 我的数据库参考 databaseReference child user getUid setValue userInformations 您需要使用以下代码 databaseRef
  • 将 List 转换为 JSON

    Hi guys 有人可以帮助我 如何将我的 HQL 查询结果转换为带有对象列表的 JSON 并通过休息服务获取它 这是我的服务方法 它返回查询结果列表 Override public List

随机推荐

  • Kafka - a simple consumer demo - c++

    Kafka 如果有 kafka 基础的同学可以不用看前面的废话 可以从第五条 配置 开始看起 代码在第七条 前言 官网比我这标准多了 官网跳转 大家可以先完成quickStart部分kafka单机生产消费 一 概念简介 Kafka 是一个分
  • 谷歌语法(详解+举例)

    一 谷歌语法是什么 谷歌语法就是利用搜索引擎在渗透测试过程搜索到特定页面的一种语法 二 如何利用谷歌语法 谷歌语法基础的符号 xxx 将要搜索的关键字用引号括起来 表示完全匹配 即关键词不能分开 顺序也不能变 例如 腾讯课堂如果不加 的话
  • 内存时延效能

    时延 Latency 小张一看到这个图 不禁大叫 太复杂了 看得我都犯密集恐惧症了 看不懂 没关系 我们拆开了一个个看 1 CL CAS Latency CL是指CAS发出之后 仍要经过一定的时间才能有数据输出 从CAS与读取命令发出到第一
  • 【华为OD统一考试A卷

    华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为OD统一考试 A卷 和OD统一考试 B卷 你收到的链接上面会标注A卷还是B卷 请注意 根据反馈 目前大部分收到的都是
  • 在云服务器存储数据的10个好处

    本文编辑 富哥 云服务器已经成为最适合在线存储数据的选项 在较早时期 大多数公司依靠内部服务器来存储他们不断增长的数据和在线文件 但今天将数据存储在在线的云服务器中已经成为新的趋势 因为它允许无限存储 将所有数据存储在云中最好的方面是确保可
  • Java中类的构成

    Java中的每个类一般包含属性 构造器 块 方法 内部类五部分 属性 用来定义对象的数据 构造器 构造器也是方法 每一个类中都一定会有构造器 包含有参构造器和无参构造器每一个对象在创建的时候都会调用构造器 如果没有构造器 系统将提供一个默认
  • 十大经典排序算法总结

    https blog csdn net hellozhxy article details 79911867
  • AI嵌入式全景:各厂商、系列和开发工具的综合概览

    要看几个方面 1 算力 2 支持何种模型 3 是否支持可视化的窗口系统 一般而言各个平台均采用linux操作系统 官方提供对应SDK 安装好后可使用硬件加速资源 而且如果要使用其硬件加速 一般都要完成模型转换 将模型转为该平台所特有的格式
  • Spring Boot 学习研究笔记(十) -SpringBoot JAP 踩坑总结

    SpringBoot JAP 踩坑总结 一 JSON 字段映射处理流程 1 实现类型转换接口 package com call show common utils import com fasterxml jackson core Json
  • 最简单的鼠标放置悬停显示省略的内容,为标签的title赋值

    翻了一下午没看到能看懂的代码 对于我这个后台开发实在天书一般 原始需求为 内容过长显示为省略号 鼠标放置时再将全部内容悬浮展示出来 内容是放置在p标签中的 设置一下style即可 注意这四个属性缺一不可 p style width 100
  • 雪花算法记录

    引子 伴随着业务的日渐庞大 单库单表的数据库可能无法支持业务的读写 需要对数据库进行分库分表 原来数据库中 通常使用自增id的方式生成主键 分库分表之后 如果仍然采用原来的方式 在多个表之间主键会发生重复 分库分表后 如何保证多张表中的 i
  • webpack5+mockjs

    上篇提到升级 vue cli 5 0 1后 发现webpack 是v5 之前配置devServer after异常 于是认真看了一下文档 webpack v5文档 v5的devServer去掉了get和after 添加了setupMiddl
  • 日期的生成

    获取系统当前时间 日期类型为timestamp 日期格式为2010 11 04 16 19 42 方法1 Timestamp d new Timestamp System currentTimeMillis 方法2 Date date ne
  • 实对称矩阵的性质_今天行列式的矩阵是一个实对称矩阵, 主对角线是同一个元素, 其余位置是另一元素。该矩阵的行列式有相当好的性质, 同学们要加以记忆...

    行列式计算 5 01 前言 1 今天我们继续讨论特殊行列式的计算思路与方法 今天这组题的行列式的矩阵是一个实对称矩阵 主对角线是同一个元素 其余位置是另一元素 该矩阵的行列式有相当好的性质 需要同学们加以记忆 2 第1题 第一个行列式的计算
  • MyBatis - 14 - 分页插件的配置及使用

    文章目录 1 分页插件配置 1 在pom xml中添加依赖 2 在MyBatis的核心配置文件中配置插件 2 分页插件的使用 回顾Mysql分页功能 MyBatis分页插件的使用 测试显示第1页 每页显示4条数据 打印page对象 测试获取
  • java Collection和Map接口的区别

    一 Collection接口 Collection是最基本的集合接口 一个Collection代表一组Object 即Collection的元素 Elements 一些Collection允许相同的元素而另一些不行 一些能排序而另一些不行
  • 荔枝派Zero(全志V3S)驱动开发之hello驱动程序

    文章目录 前言 一 设备驱动分类 二 字符设备驱动简介 三 字符设备驱动开发 1 APP打开的文件在内核中如何表示 2 编写驱动程序的步骤 3 hello 驱动程序编写 lt 1 gt 试验程序编写 lt 2 gt 测试程序编写 lt 3
  • Maven的Pom文件中的隐式依赖导致Jar包冲突的问题

    分享一下我老师大神的人工智能教程 http blog csdn net jiangjunshow 也欢迎大家转载本篇文章 分享知识 造福人民 实现我们中华民族伟大复兴 在一次的maven项目中遇到这样一个bug 编译器没有报什么错 但无法编
  • python爬取boss直聘招聘信息_python学习之路-爬取boss直聘的岗位信息

    背景 想了解从事python相关岗位需要具备什么技能 于是就想从招聘网站上的职位需求入手 把信息获取下来后 生成词云 这样就能很直观的看出来哪些技能是python相关岗位需要具备的了 技术概览 scrapy request wordclou
  • 面试官:说一下单点登录的几种实现方式

    Java面试笔试面经 Java技术每天学习一点 Java面试 关注不迷路 作者 张永恒 来源 https www cnblogs com yonghengzh p 13712729 html 在 B S 系统中 登录功能通常都是基于Cook