单点登录(原理与代码)

article/2025/9/21 10:33:02

文章目录

    • 一、单点登录简介
      • SSO 原理(单点登录的过程)
      • SSO 实现技术
      • SSO 常见方案
    • 二、手写单点登录系统架构(代码篇)
    • 三、单点登录详介(原理篇)
      • 1.登录
      • 2.注销
      • 单点登陆的具体实现:
      • 1.sso-client拦截未登录请求
      • 2.sso-server拦截未登录请求
      • 3.sso-server验证用户登录信息
      • 4.sso-server创建授权令牌
      • 5.sso-client取得令牌并校验
      • 6.sso-server接收并处理校验令牌请求
      • 7.sso-client校验令牌成功创建局部会话
      • 8.注销过程

一、单点登录简介

什么是单点登录:⼀处登录,处处登录,⼀处登出,处处登出。
⽤户只需要登录⼀次就可以访问所有相互信任的应⽤系统。
SSO
Single Sign On 单点登录——企业业务整合解决⽅案。
生活实例举例:⼀票通,景点联票。

SSO 原理(单点登录的过程)

(结合示例说明)

  • 当⽤户第⼀次访问淘宝的时候,因为还没有登录,会被引导到认证中⼼进⾏登录。
  • 根据⽤户提供的登录信息,认证系统进⾏身份验证,如果通过,则登录成功,并返回给⽤户⼀个认证的凭据(token)。
  • 当⽤户访问天猫时,就会将这个 token 带上,作为⾃⼰认证的凭据。
  • 应⽤系统接收到请求后会把 token 送到认证中⼼进⾏校验,检查 token 的合法性。
  • 如果通过校验,⽤户就可以在不⽤再次登录的情况下访问天猫了。

补充:token 是在服务端产生的。如果前端使用用户名/密码向服务端请求认证,服务端认证成功,那么在服务端会返回 token 给前端。前端可以在每次请求的时候带上 token 证明自己的合法地位。如果这个 token 在服务端持久化(比如存入数据库),那它就是一个永久的身份令牌。
在这里插入图片描述

下图是CAS官网上的标准流程,具体流程如下
在这里插入图片描述

  • 1、用户访问app系统,app系统是需要登录的,但用户现在没有登录。
  • 2、跳转到CAS server,即SSO登录系统,以后图中的CAS Server我们统一叫做SSO系统。 SSO系统也没有登录,弹出用户登录页。
  • 3、用户填写用户名、密码,SSO系统进行认证后,将登录状态写入SSO的session,浏览器(Browser)中写入SSO域下的Cookie。
  • 4、SSO系统登录完成后会生成一个ST(Service Ticket),然后跳转到app系统,同时将ST作为参数传递给app系统。
  • 5、app系统拿到ST后,从后台向SSO发送请求,验证ST是否有效。
  • 6、验证通过后,app系统将登录状态写入session并设置app域下的Cookie。

至此,跨域单点登录就完成了。以后我们再访问app系统时,app就是登录的。接下来,我们再看看访问app2系统时的流程。

  • 1、用户访问app2系统,app2系统没有登录,跳转到SSO。
  • 2、由于SSO已经登录了,不需要重新登录认证。
  • 3、SSO生成ST,浏览器跳转到app2系统,并将ST作为参数传递给app2。
  • 4、app2拿到ST,后台访问SSO,验证ST是否有效。
  • 5、验证成功后,app2将登录状态写入session,并在app2域下写入Cookie。

这样,app2系统不需要走登录流程,就已经是登录了。SSO,app和app2在不同的域,它们之间的session不共享也是没问题的。

SSO 实现技术

  • 1.Cookie 单点登录

使⽤ Cookie 作为媒介,存放⽤户凭证。
⽤户登录淘宝之后,返回⼀个 token,存⼊客户端的 Cookie 中,当⽤户访问天猫的时候,会⾃动带上 Cookie,这样 token ⼜传给了认证中⼼,进⾏校验。

  • 2.分布式 Session
    在这里插入图片描述

1、⽤户第⼀次登录时,将会话信息,写⼊分布式 Session。
2、⽤户再次登录时,获取分布式 Session,判断是否有登录信息,如果没有则返回登录⻚⾯。
3、Session ⼀般存储到 Redis 中,因为它有持久化功能,如果分布式 Session 宕机后,重启之后可以从持久化存储中重新加载会话信息。

SSO 常见方案

  • 1.OAuth2(第三方登录授权)

第三⽅系统访问主系统资源,⽤户⽆需将主系统的账户告知第三⽅,只需要通过主系统的授权,第三⽅就可以使⽤主系统的资源。

  • 2.jwt

Json Web Token,是为了在⽹络应⽤之间传递信息⽽执⾏的⼀种,基于 JSON 的开放标准,难度较⾼,需要了解很多协议,偏向底层的东⻄,需要你基于 JWT 认证协议,⾃⼰开放 SSO 服务和权限控制。

  • 3.CAS(不是并发的 CAS)

中央认证服务,Central Authentication ServiceCAS 是耶鲁⼤学发起的⼀个开源项⽬,为 Web 应⽤系统提供单点登录的解决⽅案,实现多个系统只需要登录⼀次,⽆需重复登录。

二、手写单点登录系统架构(代码篇)

Cookie 单点登录的实现(更注重底层)

  • 开始写代码:
  • CAS Server
  • CAS Client
    Server 和 Client 分别独⽴部署,Server 主要负责认证工作,Client 负责处理对客户端资源的访问请求,需要登录时,重定向到Server 进⾏认证。
    1、授权服务器保存⼀个全局 session,多个客户端各⾃保存⾃⼰的session。
    2、客户端登录时判断⾃⼰的 session 是否已经登录,如果没有登录,则重定向到服务器进⾏授权(带上⾃⼰的地址,⽤于回调)。
    3、授权服务器判断全局的 session 是否已经登录,如果未登录则重定向到登录⻚⾯,提供⽤户登录,登录成功之后,授权服务器重定向到客户端,带上 token。
    4、客户端收到 token 后,请求服务器获取⽤户信息。
    5、服务器同意客户端授权后,服务器保存⽤户信息到全局session,客户端将⽤户信息保存⾄本地 session。
    用到的技术框架:Spring Boot + layui + Thymelaf
    在这里插入图片描述
    在父工程下创建三个子模块(maven模块):
  • taobao sso_client_taobao
  • tmall sso_client_tmall
  • server sso_server

本代码git地址(下载即可使用):https://github.com/liuwen766/SSO.git
代码结构如下:
在这里插入图片描述
操作说明(ReadMe):
登录测试:
step1:
访问淘宝页面,输入:
http://localhost:8081/taobao
会验证token,若token为空,返回登录页面
username:admin password:123123
登录成功后,
step2:
访问天猫页面,输入:
http://localhost:8082/tmall
验证token,若token正确,直接登录天猫页面(不用再输入用户名,密码)
登出测试:
step1:在两个页面已登录状态,任意退出登录一个页面;
step2:刷新另一个页面,页面自动登出。

三、单点登录详介(原理篇)

(这里代码仅仅用于示例,与上面的git仓库里的代码略有不同)
什么是单点登录?单点登录全称Single Sign On(以下简称SSO),是指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分。

1.登录

相比于单系统登录,sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。这个过程,也就是单点登录的原理,用下图说明:
在这里插入图片描述

下面对上图简要描述

  1. 用户访问系统1的受保护资源,系统1发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
  2. sso认证中心发现用户未登录,将用户引导至登录页面
  3. 用户输入用户名密码提交登录申请
  4. sso认证中心校验用户信息,创建用户与sso认证中心之间的会话,称为全局会话,同时创建授权令牌
  5. sso认证中心带着令牌跳转会最初的请求地址(系统1)
  6. 系统1拿到令牌,去sso认证中心校验令牌是否有效
  7. sso认证中心校验令牌,返回有效,注册系统1
  8. 系统1使用该令牌创建与用户的会话,称为局部会话,返回受保护资源
  9. 用户访问系统2的受保护资源
  10. 系统2发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
  11. sso认证中心发现用户已登录,跳转回系统2的地址,并附上令牌
  12. 系统2拿到令牌,去sso认证中心校验令牌是否有效
  13. sso认证中心校验令牌,返回有效,注册系统2
  14. 系统2使用该令牌创建与用户的局部会话,返回受保护资源

  用户登录成功之后,会与sso认证中心及各个子系统建立会话,用户与sso认证中心建立的会话称为全局会话,用户与各个子系统建立的会话称为局部会话,局部会话建立之后,用户访问子系统受保护资源将不再通过sso认证中心,全局会话与局部会话有如下约束关系

  1. 局部会话存在,全局会话一定存在
  2. 全局会话存在,局部会话不一定存在
  3. 全局会话销毁,局部会话必须销毁

2.注销

单点登录自然也要单点注销,在一个子系统中注销,所有子系统的会话都将被销毁,用下面的图来说明
在这里插入图片描述
sso认证中心一直监听全局会话的状态,一旦全局会话销毁,监听器将通知所有注册系统执行注销操作,下面对上图简要说明

  1. 用户向系统1发起注销请求
  2. 系统1根据用户与系统1建立的会话id拿到令牌,向sso认证中心发起注销请求
  3. sso认证中心校验令牌有效,销毁全局会话,同时取出所有用此令牌注册的系统地址
  4. sso认证中心向所有注册系统发起注销请求
  5. 各注册系统接收sso认证中心的注销请求,销毁局部会话
  6. sso认证中心引导用户至登录页面

单点登陆的具体实现:

  这里只是简要介绍下基于java的实现过程,不提供完整源码,用于明白原理。sso采用客户端/服务端架构,我们先看sso-client与sso-server要实现的功能(下面:sso认证中心=sso-server)
  sso-client
1 . 拦截子系统未登录用户请求,跳转至sso认证中心
2 . 接收并存储sso认证中心发送的令牌
3 . 与sso-server通信,校验令牌的有效性
4 . 建立局部会话
5 . 拦截用户注销请求,向sso认证中心发送注销请求
6 . 接收sso认证中心发出的注销请求,销毁局部会话
  sso-server
1 . 验证用户的登录信息
2 . 创建全局会话
3 . 创建授权令牌
4 . 与sso-client通信发送令牌
5 . 校验sso-client令牌有效性
6 . 系统注册
7 . 接收sso-client注销请求,注销所有会话

接下来,按照原理来一步步实现sso!

1.sso-client拦截未登录请求

java拦截请求的方式有servlet、filter、listener三种方式,我们采用filter。在sso-client中新建LoginFilter.java类并实现Filter接口,在doFilter()方法中加入对未登录用户的拦截

public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) request;HttpServletResponse res = (HttpServletResponse) response;HttpSession session = req.getSession();if (session.getAttribute("isLogin")) {chain.doFilter(request, response);return;}//跳转至sso认证中心res.sendRedirect("sso-server-url-with-system-url");
}

2.sso-server拦截未登录请求

拦截从sso-client跳转至sso认证中心的未登录请求,跳转至登录页面,这个过程与sso-client完全一样

3.sso-server验证用户登录信息

用户在登录页面输入用户名密码,请求登录,sso认证中心校验用户信息,校验成功,将会话状态标记为“已登录”

@RequestMapping("/login")
public String login(String username, String password, HttpServletRequest req) {this.checkLoginInfo(username, password);req.getSession().setAttribute("isLogin", true);return "success";
}

4.sso-server创建授权令牌

授权令牌是一串随机字符,以什么样的方式生成都没有关系,只要不重复、不易伪造即可,下面是一个例子

String token = UUID.randomUUID().toString();

5.sso-client取得令牌并校验

sso认证中心登录后,跳转回子系统并附上令牌,子系统(sso-client)取得令牌,然后去sso认证中心校验,在LoginFilter.java的doFilter()中添加几行

// 请求附带token参数
String token = req.getParameter("token");
if (token != null) {// 去sso认证中心校验tokenboolean verifyResult = this.verify("sso-server-verify-url", token);if (!verifyResult) {res.sendRedirect("sso-server-url");return;}chain.doFilter(request, response);
}

verify()方法使用httpClient实现,这里仅简略介绍,httpClient详细使用方法请参考官方文档

HttpPost httpPost = new HttpPost("sso-server-verify-url-with-token");
HttpResponse httpResponse = httpClient.execute(httpPost);

6.sso-server接收并处理校验令牌请求

用户在sso认证中心登录成功后,sso-server创建授权令牌并存储该令牌,所以,sso-server对令牌的校验就是去查找这个令牌是否存在以及是否过期,令牌校验成功后sso-server将发送校验请求的系统注册到sso认证中心(就是存储起来的意思)
  令牌与注册系统地址通常存储在key-value数据库(如redis)中,redis可以为key设置有效时间也就是令牌的有效期。redis运行在内存中,速度非常快,正好sso-server不需要持久化任何数据。
  令牌与注册系统地址可以用下图描述的结构存储在redis中,可能你会问,为什么要存储这些系统的地址?如果不存储,注销的时候就麻烦了,用户向sso认证中心提交注销请求,sso认证中心注销全局会话,但不知道哪些系统用此全局会话建立了自己的局部会话,也不知道要向哪些子系统发送注销请求注销局部会话
在这里插入图片描述

7.sso-client校验令牌成功创建局部会话

令牌校验成功后,sso-client将当前局部会话标记为“已登录”,修改LoginFilter.java,添加几行

if (verifyResult) {session.setAttribute("isLogin", true);
}

  sso-client还需将当前会话id与令牌绑定,表示这个会话的登录状态与令牌相关,此关系可以用java的hashmap保存,保存的数据用来处理sso认证中心发来的注销请求

8.注销过程

用户向子系统发送带有“logout”参数的请求(注销请求),sso-client拦截器拦截该请求,向sso认证中心发起注销请求

String logout = req.getParameter("logout");
if (logout != null) {this.ssoServer.logout(token);
}

sso认证中心也用同样的方式识别出sso-client的请求是注销请求(带有“logout”参数),sso认证中心注销全局会话

@RequestMapping("/logout")
public String logout(HttpServletRequest req) {HttpSession session = req.getSession();if (session != null) {session.invalidate();//触发LogoutListener}return "redirect:/";
}

sso认证中心有一个全局会话的监听器,一旦全局会话注销,将通知所有注册系统注销

public class LogoutListener implements HttpSessionListener {@Overridepublic void sessionCreated(HttpSessionEvent event) {}@Overridepublic void sessionDestroyed(HttpSessionEvent event) {//通过httpClient向所有注册系统发送注销请求}
}

http://chatgpt.dhexx.cn/article/kAUEPlER.shtml

相关文章

单点登录设计原理

本文以某新闻单位多媒体数据库系统为例,提出建立企业用户认证中心,实现基于安全策略的统一用户管理、认证和单点登录,解决用户在同时使用多个应用系统时所遇到的重复登录问题。 随着信息技术和网络技术的迅猛发展,企业内部的应用…

单点登录SSO的原理

思考: web系统早已从久远的单系统发展成为如今由多系统组成的应用群,面对如此众多的系统,用户难道要一个一个登录、然后一个一个注销吗? 当然不是,web系统由单系统发展成多系统组成的应用群,复杂性应该由系统内部承担&#xff0c…

单点登录原理与代码实现

GitHub:https://github.com/sheefee/simple-sso 一、单系统登录机制 1、http无状态协议 web应用采用browser/server架构,http作为通信协议。http是无状态协议,浏览器的每一次请求,服务器会独立处理,不与之前或之后的…

单点登录的实现原理

转自:https://www.cnblogs.com/UliiAn/p/3803042.html https://blog.csdn.net/javaloveiphone/article/details/52439613 单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用,而在架构单…

单点登录原理与实现

用 10 张图给你说明白单点登录原理与实现 欢迎来到,德莱联盟! 今天盟主给你们讲一讲单点登录,还有它的具体实现。 一、单系统登录机制 1、http无状态协议 web应用采用browser/server架构,http作为通信协议。http是无状态协议&…

什么是单点登录?如何实现?

一、是什么 单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一 SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统 SSO 一般都需要一个独立的认证中…

SSO单点登录原理详解

本文主要对SSO单点登录与CAS、OAuth2.0两种授权协议的关系和原理进行详细说明。 1. 基础概念 术语解释 SSO-Single Sign On,单点登录 TGT-Ticket Granting Ticket,用户身份认证凭证票据 ST-Service Ticket&#xf…

10.单点登录原理及JWT实现

单点登录原理及JWT实现 一、单点登录效果 首先我们看通过一个具体的案例来加深对单点登录的理解。案例地址:https://gitee.com/xuxueli0323/xxl-sso?_fromgitee_search 把案例代码直接导入到IDEA中 然后分别修改下server和samples中的配置信息 在host文件中配置 …

单点登录SSO的实现原理

单点登录SSO(Single Sign On)说得简单点就是在一个多系统共存的环境下,用户在一处登录后,就不用在其他系统中登录,也就是用户的一次登录能得到其他所有系统的信任。单点登录在大型网站里使用得非常频繁,例如…

单点登录原理及实现

一,背景 单点登录顾名思义就是在多个应用系统中,只需要登录一次,就可以访问其他相互信任的应用系统,免除多次登录的烦恼。比如我们登录了百度账号,再去百度百科,百度文库就不需要再次登录了。 二&#xf…

CGAL:学习CGAL

背景 CGAL是一个非常有用的库,但是学习起来非常痛苦。为此,我们计划通过一些小的demo,逐渐学习CGAL的使用方法。目前,由于我们还缺少对CGAL的整体把握,所以demo没有连贯性,且难度飘忽不定。不过随着我们的…

CGAL例程:点云数据三维重建

作者:西蒙吉罗多 链接:CGAL 5.4 - Manual: Surface Reconstruction from Point Cloudshttps://doc.cgal.org/latest/Manual/tuto_reconstruction.html 目录 2 我应该使用哪种算法? 3 管道概览 4 读取点云数据 5 点云预处理 5.1 异常值…

CGAL编译与配置

从来没有自己编译过第三方库,每次看到cmake上那些红色的错误就头疼,从来都是伸手党,不过这次没有要到编译好的CGAL,只能硬着头皮自己来。当编译完看到自己的例子跑通,才发现并没有想象中的复杂。 (此方法在win7和win1…

CGAL的使用

1 C++类的知识 因为CGAL是用C++实现的,所以需要先了解一下C++编程。C++是面向对象的编程,这也是C++对C语言改进的最重要的部分。C++也被叫做是"带类的 C"。简单讲一下类的构成,成员函数以及对象的定义和使用。 1.1 C++类的构成 首先从C的结构体说起。C中的结构体我想…

cgal配置以及一些资料

Win7下VS2008编译CGAL3.9 (转:http://blog.csdn.net/wsh6759/article/details/6977847) CGAL是比较经典的计算几何库,算法经典,稳定高效。 本文介绍编译CGAl情况, 前期准备: BOOST&#x…

CGAL学习记录

CGAL学习记录 前言CGAL 介绍CGAL Linux安装CGAL Windos安装CGAL 安装错误及解决办法CGAL 安装后测试CGAL I/O读写 FunctionsCGAL OFF数据格式CGAL OFF STL相互转换CGAL 表面细化CGAL 表面平滑CGAL 表面补洞CGAL 自相交检测CGAL 提取中心线 前言 原先使用vtk有些小地方不是很理…

CGAL Cookbook --CGAL简介

##前言 ## 接触CGAL已经有半年了,从最初的厌恶(对于一个初学者来说,CGAL确实有点难度,它要求初学者有一定基础)到后来的喜欢。现在觉得CGAL简直完美极了,虽然它存在一些BUG但是这并不妨碍我爱上CGAL。它的…

[CGAL] CGAL的编译与使用

文章目录 方法一:自己安装依赖库安装Boost安装CGAL安装Qt编译示例在VS中使用CGAL库引用boost引用gmp引用CGALHelloworld 报错处理在cmake配置时报错:未能找到Boost编译示例,未找到GMP编译Mesh_3例子报错:未能找到Eigen3编译demo/P…

CGAL学习之路(三):CGAL读写点云

文章目录 1 CGAL创建点云1.1 insert方式1.2 迭代器方式 2 CGAL读点云2.1 读取XYZ点云2.2 读取PLY点云2.3 ifstream读取XYZ \ PLY点云 3 CGAL输出点坐标3.1 输出点云所有坐标3.2 输出某一点的坐标3.3 输出XYZ坐标 4 CGAL保存点云(XYZ | PLY)5 添加法向量字…

【C++】CGAL学习笔记

一、HELLO WORLD 1. 官方文档:CGAL-TUTORIALS 2. 所有CGAL头文件都在子目录中。所有CGAL类和函数都在命名空间中。类以大写字母开头,全局函数以小写字母开头,常量全部大写。 3. 几何图元,如点、线等都定义在内核Kernel中 #inc…