您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

单点登录(SSO)看这一篇还不够!这次不慌了

时间:2021-12-23 11:47:45  来源:  作者:程序yuan
单点登录(SSO)看这一篇还不够!这次不慌了

 

阅读收获

✔️1. 了解单点登录实现原理

✔️2. 掌握快速使用xxl-sso接入单点登录功能

一、早期的多系统登录解决方案

  • 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器与服务器之间维护会话状态。但cookie是有限制的,这个限制就是cookie的域(通常对应网站的域名),浏览器发送http请求时会自动携带与该域匹配的cookie,而不是所有cookie
  • 既然这样,为什么不将web应用群中所有子系统的域名统一在一个顶级域名下,例如“*.baidu.com”,然后将它们的cookie域设置为“baidu.com”,这种做法理论上是可以的,甚至早期很多多系统登录就采用这种同域名共享cookie的方式。
  • 共享cookie的方式存在众多局限。
    • 应用群域名得统一
    • 应用群各系统使用的技术(至少是web服务器)要相同,不然cookie的key值(Tomcat为JSESSIONID)不同,无法维持会话,共享cookie的方式是无法实现跨语言技术平台登录的,比如JAVAphp、.net系统之间
    • cookie本身不安全。
  • 因此,我们需要一种全新的登录方式来实现多系统应用群的登录,这就是单点登录

二、什么是单点登录

  • 单点登录英文全称Single Sign On,简称SSO。
  • 指在多系统应用群中登录一个系统,便可在其他所有系统中得到授权而无需再次登录,包括单点登录与单点注销两部分

三、为什么需要单点登录

  • web系统早已从久远的单系统发展成为如今由多系统组成的应用群,面对如此众多的系统,用户难道要一个一个登录、然后一个一个注销吗?
  • web系统由单系统发展成多系统组成的应用群,复杂性应该由系统内部承担,而不是用户。无论web系统内部多么复杂,对用户而言,都是一个统一的整体,也就是说,用户访问web系统的整个应用群与访问单个系统一样,登录/注销只要一次就够了

四、单点登录原理

4.1 登录

sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。

间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。

这个过程,也就是单点登录的原理,用下图说明

单点登录(SSO)看这一篇还不够!这次不慌了

 

  1. 用户访问系统1的受保护资源,系统1发现用户未登录,跳转至sso认证中心,并将自己的地址作为参数
  2. sso认证中心发现用户未登录,将用户引导至登录页面(带系统1地址)
  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. 全局会话销毁,局部会话必须销毁

4.2 注销

在一个子系统中注销,所有子系统的会话都将被销毁,用下面的图来说明

单点登录(SSO)看这一篇还不够!这次不慌了

 

sso认证中心一直监听全局会话的状态,一旦全局会话销毁,监听器将通知所有注册系统执行注销操作

下面对上图简要说明

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

五、快速接入SSO

5.1 xxl-sso特性

  • 简洁:API直观简洁,可快速上手
  • 轻量级:环境依赖小,部署与接入成本较低
  • 单点登录:只需要登录一次就可以访问所有相互信任的应用系统
  • 分布式:接入SSO认证中心的应用,支持分布式部署
  • HA:Server端与Client端,均支持集群部署,提高系统可用性
  • 跨域:支持跨域应用接入SSO认证中心
  • Cookie+Token均支持:支持基于Cookie和基于Token两种接入方式,并均提供Sample项目
  • Web+App均支持:支持Web和APP接入
  • 实时性:系统登陆、注销状态,全部Server与Client端实时共享
  • CS结构:基于CS结构,包括Server"认证中心"与Client"受保护应用"
  • 记住密码:未记住密码时,关闭浏览器则登录态失效;记住密码时,支持登录态自动延期,在自定义延期时间的基础上,原则上可以无限延期
  • 路径排除:支持自定义多个排除路径,支持Ant表达式,用于排除SSO客户端不需要过滤的路径

5.2 环境

  • JDK:1.7+
  • redis:4.0+

5.3 下载xxl-sso源码

源码仓库地址

Release Download

github.com/xuxueli/xxl…

Download

gitee.com/xuxueli0323…

Download

5.4 文档地址

  • 中文文档

5.5 项目结构说明

- xxl-sso-server:中央认证服务,支持集群
- xxl-sso-core:Client端依赖
- xxl-sso-samples:单点登陆Client端接入示例项目
    - xxl-sso-web-sample-springboot:基于Cookie接入方式,供用户浏览器访问,springboot版本
    - xxl-sso-token-sample-springboot:基于Token接入方式,常用于无法使用Cookie的场景使用,如APP、Cookie被禁用等,springboot版本
复制代码

5.6 基于Token方式部署

  • 由于前后端分离开发的模式较多,这里只介绍基于Token方式部署,在一些无法使用Cookie的场景下,可使用该方式,如需要Cookie查看基于cookie方式部署

5.6.1 认证中心(SSO Server)搭建

  • 项目名:xxl-sso-server
  • 配置文件位置:application.properties
### redis 地址: 如 "{ip}"、"{ip}:{port}"、"{redis/rediss}://xxl-sso:{password}@{ip}:{port:6379}/{db}";多地址逗号分隔
xxl.sso.redis.address=redis://127.0.0.1:6379
### 登录态有效期窗口,默认24H,当登录态有效期窗口过半时,自动顺延一个周期
xxl.sso.redis.expire.minute=1440
复制代码

5.6.2 单点登陆Client端搭建

  • 项目名:xxl-sso-token-sample-springboot
  • maven依赖
<dependency>
    <groupId>com.xuxueli</groupId>
    <artifactId>xxl-sso-core</artifactId>
    <version>${最新稳定版}</version>
</dependency>
复制代码
  • 配置文件:application.properties
##### SSO Server认证中心地址(推荐以域名方式配置认证中心)
xxl.sso.server=http://xxlssoserver.com:8080/xxl-sso-server

##### 注销登陆path,值为Client端应用的相对路径
xxl.sso.logout.path=/logout

##### 路径排除Path,允许设置多个,且支持Ant表达式。用于排除SSO客户端不需要过滤的路径
xxl-sso.excluded.paths=

### redis   // redis address, like "{ip}"、"{ip}:{port}"、"{redis/rediss}://xxl-sso:{password}@{ip}:{port:6379}/{db}";Multiple "," separated
xxl.sso.redis.address=redis://xxl-sso:password@127.0.0.1:6379/0
xxl.sso.redis.address=redis://127.0.0.1:6379
复制代码
  • 配置 XxlSsoTokenFilter
package com.xxl.sso.sample.config;

import com.xxl.sso.core.conf.Conf;
import com.xxl.sso.core.filter.XxlSsoTokenFilter;
import com.xxl.sso.core.util.JedisUtil;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

/**
 * @author xuxueli 2018-11-15
 */
@Configuration
public class XxlSsoConfig implements DisposableBean {


    @Value("${xxl.sso.server}")
    private String xxlSsoServer;

    @Value("${xxl.sso.logout.path}")
    private String xxlSsoLogoutPath;

    @Value("${xxl.sso.redis.address}")
    private String xxlSsoRedisAddress;

    @Value("${xxl-sso.excluded.paths}")
    private String xxlSsoExcludedPaths;


    @Bean
    public FilterRegistrationBean xxlSsoFilterRegistration() {

        // xxl-sso, redis init
        JedisUtil.init(xxlSsoRedisAddress);

        // xxl-sso, filter init
        FilterRegistrationBean registration = new FilterRegistrationBean();

        registration.setName("XxlSsoWebFilter");
        registration.setOrder(1);
        registration.addUrlPatterns("/*");
        //token使用的是XxlSsoTokenFilter
        registration.setFilter(new XxlSsoTokenFilter());
        registration.addInitParameter(Conf.SSO_SERVER, xxlSsoServer);
        registration.addInitParameter(Conf.SSO_LOGOUT_PATH, xxlSsoLogoutPath);
        registration.addInitParameter(Conf.SSO_EXCLUDED_PATHS, xxlSsoExcludedPaths);

        return registration;
    }

    @Override
    public void destroy() throws Exception {

        // xxl-sso, redis close
        JedisUtil.close();
    }

}
复制代码

5.6.3 验证 (模拟请求 Token 方式接入SSO的接口)

  • 修改Host文件:域名方式访问认证中心,模拟跨域与线上真实环境
### 在host文件中添加以下内容0
127.0.0.1 xxlssoserver.com
127.0.0.1 xxlssoclient1.com
127.0.0.1 xxlssoclient2.com
复制代码
  • 分别运行 "xxl-sso-server" 与 "xxl-sso-token-sample-springboot"
  • 认证中心搭建成功后,默认为Token方式登陆提供API接口:
  • 1、登陆接口:/app/login参数:POST参数username:账号password:账号响应:JSON格式code:200 表示成功、其他失败msg:错误提示data: 登陆用户的 sso sessionid
  • 2、注销接口:/app/logout参数:POST参数sessionId:登陆用户的 sso sessionid响应:JSON格式code:200 表示成功、其他失败msg:错误提示
  • 3、登陆状态校验接口:/app/logincheck参数:POST参数sessionId:登陆用户的 sso sessionid响应:JSON格式code:200 表示成功、其他失败msg:错误提示data:登陆用户信息userid:用户IDusername:用户名
  • idea的http client测试如下:
##client1
POST http://xxlssoclient1.com:8082/xxl-sso-token-sample-springboot/
Content-Type: application/x-www-form-urlencoded
xxl_sso_sessionid: 1000_bac4555c627e4233b6da7d3f9b91aff5

###

##client2
http://xxlssoclient2.com:8082/xxl-sso-token-sample-springboot/
Content-Type: application/x-www-form-urlencoded
xxl_sso_sessionid: 1000_bac4555c627e4233b6da7d3f9b91aff5



###

##校验
POST http://xxlssoserver.com:8080/xxl-sso-server/app/logincheck
Content-Type: application/x-www-form-urlencoded

sessionId=1000_9df8ee645d7f435fb5f76c9223dfe6e8


###

##注销
POST http://xxlssoserver.com:8080/xxl-sso-server/app/logout
Content-Type: application/x-www-form-urlencoded

sessionId=1000_0ec8e28158da4241926314e0b3b9b834


###

#登录sso
POST http://xxlssoserver.com:8080/xxl-sso-server/app/login
Content-Type: application/x-www-form-urlencoded

username=user&password=123456

复制代码
  • SSO登录/注销流程验证:
    • 可参考测试用例 :com.xxl.app.sample.test.TokenClientTest
  • 正常情况下,登录流程如下:
    • 1、获取用户输入的账号密码后,请求SSO Server的登录接口,获取用户 sso sessionid ;(参考代码:TokenClientTest.loginTest)
    • 2、登陆成功后,获取到 sso sessionid ,需要主动存储,后续请求时需要设置在 Header参数 中
    • 3、此时,使用 sso sessionid 访问受保护的 "Client01应用" 和 "Client02应用" 提供的接口,接口均正常返回(参考代码:TokenClientTest.clientApiRequestTest)
  • 正常情况下,注销流程如下:
    • 1、请求SSO Server的注销接口,注销登陆凭证 sso sessionid ;(参考代码:TokenClientTest.logoutTest)
    • 2、注销成功后,sso sessionid 将会全局失效
    • 3、此时,使用 sso sessionid 访问受保护的 "Client01应用" 和 "Client02应用" 提供的接口,接口请求将会被拦截,提示未登录并返回状态码 501(参考代码:TokenClientTest.clientApiRequestTest)

六、总体设计

6.1 架构

单点登录(SSO)看这一篇还不够!这次不慌了

 

6.2 功能定位

XXL-SSO 是一个分布式单点登录框架。只需要登录一次就可以访问所有相互信任的应用系统。

借助 XXL-SSO,可以快速实现分布式系统单点登录。

6.3 核心概念

概念

说明

SSO Server

中央认证服务,支持集群

SSO Client

接入SSO认证中心的Client应用

SSO SessionId

登录用户会话ID,SSO 登录成功为用户自动分配

SSO User

登录用户信息,与 SSO SessionId 相对应

6.4 登录流程剖析

  • 用户于Client端应用访问受限资源时,将会自动 redirect 到 SSO Server 进入统一登录界面
  • 用户登录成功之后将会为用户分配 SSO SessionId 并 redirect 返回来源Client端应用,同时附带分配的 SSO SessionId
  • 在Client端的SSO Filter里验证 SSO SessionId 无误,将 SSO SessionId 写入到用户浏览器Client端域名下 cookie 中
  • SSO Filter验证 SSO SessionId 通过,受限资源请求放行

6.5 注销流程剖析

  • 用户与Client端应用请求注销Path时,将会 redirect 到 SSO Server 自动销毁全局 SSO SessionId,实现全局销毁
  • 然后,访问接入SSO保护的任意Client端应用时,SSO Filter 均会拦截请求并 redirect 到 SSO Server 的统一登录界面

6.6 基于Cookie,相关概念

  • 登录凭证存储:登录成功后,用户登录凭证被自动存储在浏览器Cookie中
  • Client端校验登录状态:通过校验请求Cookie中的是否包含用户登录凭证判断
  • 系统角色模型:
    • SSO Server:认证中心,提供用户登录、注销以及登录状态校验等功能
    • Client应用:受SSO保护的Client端Web应用,为用户浏览器访问提供服务
    • 用户:发起请求的用户,使用浏览器访问

6.7 基于Token,相关概念

  • 登录凭证存储:登录成功后,获取到登录凭证(xxl_sso_sessionid=xxx),需要主动存储,如存储在 localStorage、Sqlite 中
  • Client端校验登录状态:通过校验请求 Header参数 中的是否包含用户登录凭证(xxl_sso_sessionid=xxx)判断;因此,发送请求时需要在 Header参数 中设置登陆凭证
  • 系统角色模型:
    • SSO Server:认证中心,提供用户登录、注销以及登录状态校验等功能
    • Client应用:受SSO保护的Client端Web应用,为用户请求提供接口服务
    • 用户:发起请求的用户,如使用AndroidIOS、桌面客户端等请求访问

6.8 未登录状态请求处理

基于Cookie,未登录状态请求:

  • 页面请求:redirect 到SSO Server登录界面
  • JSON请求:返回未登录的JSON格式响应数据
    • 数据格式:
      • code:501 错误码
      • msg:sso not login.

基于Token,未登录状态请求:

  • 返回未登录的JSON格式响应数据
    • 数据格式:
      • code:501 错误码
      • msg:sso not login.

6.9 登录态自动延期

支持自定义登录态有效期窗口,默认24H,当登录态有效期窗口过半时,自动顺延一个周期。

6.10 记住密码

未记住密码时,关闭浏览器则登录态失效;记住密码时,登录态自动延期,在自定义延期时间的基础上,原则上可以无限延期。

6.11 路径排除

自定义路径排除Path,允许设置多个,且支持Ant表达式。用于排除SSO客户端不需要过滤的路径。



Tags:单点登录(   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  Tags: 单点登录(  点击:(8)  评论:(0)  加入收藏
▌简易百科推荐
摘 要 (OF作品展示)OF之前介绍了用python实现数据可视化、数据分析及一些小项目,但基本都是后端的知识。想要做一个好看的可视化大屏,我们还要学一些前端的知识(vue),网上有很多比...【详细内容】
2021-12-27  项目与数据管理    Tags:Vue   点击:(1)  评论:(0)  加入收藏
程序是如何被执行的&emsp;&emsp;程序是如何被执行的?许多开发者可能也没法回答这个问题,大多数人更注重的是如何编写程序,却不会太注意编写好的程序是如何被运行,这并不是一个好...【详细内容】
2021-12-23  IT学习日记    Tags:程序   点击:(9)  评论:(0)  加入收藏
阅读收获✔️1. 了解单点登录实现原理✔️2. 掌握快速使用xxl-sso接入单点登录功能一、早期的多系统登录解决方案 单系统登录解决方案的核心是cookie,cookie携带会话id在浏览器...【详细内容】
2021-12-23  程序yuan    Tags:单点登录(   点击:(8)  评论:(0)  加入收藏
下载Eclipse RCP IDE如果你电脑上还没有安装Eclipse,那么请到这里下载对应版本的软件进行安装。具体的安装步骤就不在这赘述了。创建第一个标准Eclipse RCP应用(总共分为六步)1...【详细内容】
2021-12-22  阿福ChrisYuan    Tags:RCP应用   点击:(7)  评论:(0)  加入收藏
今天想简单聊一聊 Token 的 Value Capture,就是币的价值问题。首先说明啊,这个话题包含的内容非常之光,Token 的经济学设计也可以包含诸多问题,所以几乎不可能把这个问题说的清...【详细内容】
2021-12-21  唐少华TSH    Tags:Token   点击:(9)  评论:(0)  加入收藏
实现效果:假如有10条数据,分组展示,默认在当前页面展示4个,点击换一批,从第5个开始继续展示,到最后一组,再重新返回到第一组 data() { return { qList: [], //处理后...【详细内容】
2021-12-17  Mason程    Tags:VUE   点击:(14)  评论:(0)  加入收藏
什么是性能调优?(what) 为什么需要性能调优?(why) 什么时候需要性能调优?(when) 什么地方需要性能调优?(where) 什么时候来进行性能调优?(who) 怎么样进行性能调优?(How) 硬件配...【详细内容】
2021-12-16  软件测试小p    Tags:性能调优   点击:(19)  评论:(0)  加入收藏
Tasker 是一款适用于 Android 设备的高级自动化应用,它可以通过脚本让重复性的操作自动运行,提高效率。 不知道从哪里听说的抖音 app 会导致 OLED 屏幕烧屏。于是就现学现卖,自...【详细内容】
2021-12-15  ITBang    Tags:抖音防烧屏   点击:(23)  评论:(0)  加入收藏
11 月 23 日,Rust Moderation Team(审核团队)在 GitHub 上发布了辞职公告,即刻生效。根据公告,审核团队集体辞职是为了抗议 Rust 核心团队(Core team)在执行社区行为准则和标准上...【详细内容】
2021-12-15  InfoQ    Tags:Rust   点击:(24)  评论:(0)  加入收藏
一个项目的大部分API,测试用例在参数和参数值等信息会有很多相似的地方。我们可以复制API,复制用例来快速生成,然后做细微调整既可以满足我们的测试需求1.复制API:在菜单发布单...【详细内容】
2021-12-14  AutoMeter    Tags:AutoMeter   点击:(20)  评论:(0)  加入收藏
相关文章
    无相关信息
最新更新
栏目热门
栏目头条