实战:SpringBoot集成xxl-sso实现单点登录

2023-11-06

点击上方“Java之间”,选择“置顶或者星标”

你关注的就是我关心的!

前言

单点登录SSO(Single Sign On),凡是有一定的开发经验的童鞋都应该有应用或者了解过,小编还是实习生的时候,看到登录某个应用服务后,再跳转其他应用服务,竟然不用再次登录了,觉得贼拉风,不知道大家第一见这种场景时是不是跟小编一样的感觉。今天小编给大家介绍一款分布式单点登录组件xxl-sso,目的就是让大家能短时间内快速的应用到项目中,并从中了解其中的相关的实现原理。

项目介绍

xxl-sso是一款基于redis轻量级分布式高可用的SSO实现组件,支持web端(Cookie实现)和app端(Token实现)两种方式,两种方式的验证都是用Filter实现的,小编之所以叫组件不叫框架,是因为集成起来超级方便,源码也非常易懂。废话不多说,直接进入实战把。

实战

1.认证中心部署

从https://github.com/xuxueli/xxl-sso/下载项目,将xxl-sso-server单独拷贝到自己的创建的项目中(其实直接用就可以了,小编喜欢拷贝过来以便自定义修改),这个模块只需要修改下application.properties中的redis配置就可以了。

### web
server.port=8880
server.servlet.context-path=/xxl-sso-server

### resources
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/

### freemarker
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8
spring.freemarker.request-context-attribute=request
spring.freemarker.settings.number_format=0.##########

### xxl-sso  "redis://xxl-sso:password@127.0.0.1:6379/0"   redis://xxl-sso:123456@localhost:6379/0
xxl.sso.redis.address=redis://127.0.0.1:6379/0
xxl.sso.redis.expire.minite=1440

这里xxl.sso.redis.address是小编自己本地安装的redis单机默认配置信息,还可以通过逗号分隔进行集群,目前这组件只支持分片集群ShardedJedisPool,组件后续会支持JedisCluster,注意redis://{username}:{password}@{ip}:{port}/{db}这种需要密码的配置方式,密码一定不要带#,!,@,$等特殊符号,ShardedJedisPool初始化链接时会报解析错误。

启动项目,效果如下

image-20200605091638566

好了,认证中心OK了,小编项目太多了,端口这里改成了8880,contextPath为/xxl-sso-server,之所以强调端口和contextPath,是因为应用端要用到。

「注意」 : 认证中心的login接口默认是查的内存,具体业务开发中需要改成读数据库的形式。

2.应用端配置

2.1 创建一个新的spring boot module,引入核心jar

       <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
            <version>2.2.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.xuxueli</groupId>
            <artifactId>xxl-sso-core</artifactId>
            <version>1.1.0</version>
        </dependency>

2.2 修改application.properties,如下

### web
server.port=8881
server.servlet.context-path=/xxl-sso-client

### xxl-sso
xxl.sso.server=http://xxlssoserver.com:8880/xxl-sso-server
xxl.sso.logout.path=/logout
xxl-sso.excluded.paths=
xxl.sso.redis.address=redis://127.0.0.1:6379

### freemarker
spring.freemarker.request-context-attribute=request
spring.freemarker.cache=false
spring.freemarker.templateLoaderPath=classpath:/templates/
spring.freemarker.suffix=.ftl
spring.freemarker.charset=UTF-8

### resource (default: /**  + classpath:/static/ )
spring.mvc.static-path-pattern=/static/**
spring.resources.static-locations=classpath:/static/

demo用的是官方的freemarker来演示登录成功的界面,需要需要在classpath:/templates目录下放入一个页面模板,官方的代码freemarker没有配置完整,小编是踩坑后自己补全的

image-20200605093152735

「重点」 : xxl.sso.server改成认证中心的项目地址

xxl.sso.redis.address需要修改与认证中心同一个redis配置

2.3 创建配置类

@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("/*");
        //registration.setFilter(new XxlSsoTokenFilter()); //token验证方式
        registration.setFilter(new XxlSsoWebFilter()); //cookie验证方式
        //xxlSsoServer用来拼接sso server登录/登出接口,进行重定向跳转到认证中心,而且只要到登录界面就要带上回调地址,否则回跳到服务器内部默认页面
        registration.addInitParameter(Conf.SSO_SERVER, xxlSsoServer);
        //xxlSsoLogoutPath用来指定登出的路径,相对当前应用contextPath
        registration.addInitParameter(Conf.SSO_LOGOUT_PATH, xxlSsoLogoutPath);
        //xxlSsoExcludedPaths用来指定不需要校验的路径,相对当前应用contextPath,多个用逗号分隔,支持ANT表达式
        registration.addInitParameter(Conf.SSO_EXCLUDED_PATHS, xxlSsoExcludedPaths);
        return registration;
    }

    @Override
    public void destroy() throws Exception {
        // xxl-sso, redis close
        JedisUtil.close();
    }
}

cookie和token验证方式的实现是可插拔的,校验逻辑实现类为XxlSsoWebFilter(cookie)和XxlSsoTokenFilter(token),里面实现流程是一样的,只是验证的方式不一样。

「校验流程」

  • 校验排除的路径,排除不需要校验的访问路径

  • 校验contextPath后面路径是否是logout,是logout则清除认证中心放入redis的token(userId+version凭借的唯一标识)凭据

    userId是用户对象的唯一标识,version就是UUID

  • 校验凭据的合法性以及时效性

    「校验方式」

  • WEB cookie验证方式

    认证中心登录成功后,会把token存入redis并以重定向的方式传给应用端,应用端将token写入浏览器的cookie中,web端再次请求时,应用端获取HttpServletRequest中cookie中的token与redis中的token进行对比

  • APP token验证方式

    认证中心以登录接口的形式提供token并存入redis,再次访问应用端接口时,应用端会取HttpServletRequest里面的header中key为「xxl_sso_sessionid」对应的值(token)与redis中的token进行对比

    具体的对比细节,有兴趣的童鞋可以看下源码或者进行留言,大家探讨下。

3.效果演示

为了模拟多个应用端跨域场景,需要修改下hosts文件,添加如下信息

127.0.0.1 xxlssoserver.com
127.0.0.1 xxlssoclient1.com
127.0.0.1 xxlssoclient2.com

「认证中心」 初始化几个用户对象到内存中,也可以改成查数据库的形式,认证中心登录接口会调用findUser方式

@Service
public class UserServiceImpl implements UserService {

    private static List<UserInfo> mockUserList = new ArrayList<>();
    static {
        for (int i = 0; i <5; i++) {
            UserInfo userInfo = new UserInfo();
            userInfo.setUserid(1000+i);
            userInfo.setUsername("user" + (i>0?String.valueOf(i):""));
            userInfo.setPassword("123456");
            mockUserList.add(userInfo);
        }
    }

    /**
     * 登录时需要验证用户名称和密码,提供查询,可以改成数据库查询形式
     **/
    @Override
    public ReturnT<UserInfo> findUser(String username, String password) {

        if (username==null || username.trim().length()==0) {
            return new ReturnT<UserInfo>(ReturnT.FAIL_CODE, "Please input username.");
        }
        if (password==null || password.trim().length()==0) {
            return new ReturnT<UserInfo>(ReturnT.FAIL_CODE, "Please input password.");
        }
        // mock user
        for (UserInfo mockUser: mockUserList) {
            if (mockUser.getUsername().equals(username) && mockUser.getPassword().equals(password)) {
                return new ReturnT<UserInfo>(mockUser);
            }
        }
        
        return new ReturnT<UserInfo>(ReturnT.FAIL_CODE, "username or password is invalid.");
    }

}

「应用端」 添加一个跳转到登录成功页的接口,页面是上面提到的freemarker的index.flt,然后再添加一个测试接口

    @RequestMapping("/")
    public String index(Model model, HttpServletRequest request) {
        XxlSsoUser xxlUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
        model.addAttribute("xxlUser", xxlUser);
        return "index";
    }
   @RequestMapping("/json")
    @ResponseBody
    public ReturnT<XxlSsoUser> json(Model model, HttpServletRequest request) {
        XxlSsoUser xxlUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);
        return new ReturnT(xxlUser);
    }

3.1 基于cookie

设置应用端配置FilterRegistrationBean的filter如下

registration.setFilter(new XxlSsoWebFilter()); //cookie验证方式
  • 启动应用端后访问地址http://xxlssoclient1.com:8881/xxl-sso-client

image-20200605111722463

细心的童鞋会发现,地址被重定向了到认证中心的登录页,而且参数redirect_url是刚刚应用端的请求地址。

user/123456进行登录

image-20200605113554851

认证中心重定向到redirect_url的地址并带上token(xxl_sso_sessionid)参数

  • 访问预先准备好的例子,地址http://xxlssoclient2.com:8881/xxl-sso-client/json试一下,看是否还需要登录

image-20200605113400615

直接就返回结果了,跟预期一样免登录了,而且回传到应用端的token(xxl_sso_sessionid)是一样的,而且格式正是userId_UUID

  • 登出xxlssoclient1.com后看xxlssoclient2.com是否还能正常访问

image-20200605113701699

token失效了,又重新跳到了认证中心的登录页。

3.2 基于token

设置应用端配置FilterRegistrationBean的filter如下

 registration.setFilter(new XxlSsoTokenFilter());//token验证方式

重新启动应用,用postman访问认证中心的登录接口

image-20200605114324037

返回token(xxl_sso_sessionid)为1000_0422bc223a364ec89e0ac67203032e62

  • 访问应用的测试接口http://xxlssoclient1.com:8881/xxl-sso-client/json

image-20200605114434691

由于header没填入token(xxl_sso_sessionid),报501错误了,加上xxl_sso_sessionid对应的值1000_0422bc223a364ec89e0ac67203032e62,再次请求

image-20200605114718015

接口返回数据成功。

  • 试试用这个token访问http://xxlssoclient2.com:8881/xxl-sso-client/json

    image-20200605114858723
  • image

正常返回数据。

  • 调用http://xxlssoclient1.com:8881/xxl-sso-client/logout后,再看http://xxlssoclient2.com:8881/xxl-sso-client/json还能访问不

image-20200605115114743

跟预期一样,报501错误了,提示没有登录

两种方式都演示完了,是否跟童鞋们预期的一样呢?

代码获取:

https://github.com/pengziliu/GitHub-code-practice/

总结

xxl-sso大大减少了开发与维护成本,非常适用于内部多项目集成场景,耶鲁的CAS/Oauth2.0规范协议应该是目前比较常用的SSO实现,但学习成本以及配置的复杂度比xxl-sso要多很多,有兴趣的童鞋可以进行对比下。

xxl-sso目前还在持续迭代中,小编使用过程中发现登入和登出后认证中心的回调地址暂时没有参数进行配置,童鞋们可以想想怎么实现,欢迎留言,最佳方案的送礼物。

最近热文阅读:

1、为什么老外不愿意用 MyBatis?

2、Thread.sleep(0) 有什么用?

3、rm删除文件之后,空间就被释放了吗?

4、百度开源的 71 个项目,太牛逼了!

5、2020校招薪酬大比拼,你被倒挂了没?

6、那些总是写“烂代码”的同学,强烈推荐你使用这款 IDEA 插件!

7、同事说,使用存储过程挺香的!阿里巴巴为什么要禁止?

8、干掉Navicat:这个IDEA的兄弟真香!

9、一文搞定分布式系统ID生成方案

10、收藏啦~ Github上 10 个开源免费且优秀的后台控制面板

关注公众号,你想要的Java都在这里

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

实战:SpringBoot集成xxl-sso实现单点登录 的相关文章

  • Windows下Git-preview中文乱码的解决方法

    在Windows下安装Git preview 1 7 4后 使用中发现许多的乱码问题 感觉甚是不便 这是因为Git是在linux下开发的管理软件 而linux的编码方式是基于UTF 8的 所以移植到Windows之后难免会存在编码方式不同的
  • android wear 微信语音,moto 360手表语音回复微信教程

    moto360智能手表是一款搭载android系统的智能手表 目前微信已经添加了对智能手表的支持 不过很多玩家对于怎么使用moto 360语音回复微信还不是很清楚 下面小编就为大家分享一下moto 360语音回复微信教程 moto 360语
  • 最大权闭合子图(最小割)

    最大权闭合子图 最大流最小割 参考资料 1 最大权闭合子图 权闭合子图 存在一个图的子图 使得子图中的所有点出度指向的点依旧在这个子图内 则此子图是闭合子图 在这个图中有8个闭合子图 3 4 2 4 3 4 1 3 4 2 3 4 1 2
  • Qt绘图QGraphicsView、QGraphicsScene、QGraphicsItem简述

    Qt绘图中 QGraphicsView QGraphicsScene QGraphicsItem三者之间密不可分 以下简单介绍三者之间关系 三者之间关系 如同绘画的过程 Qt绘图中 QGraphicsView的作用相当于画板 QGraphi
  • linux 使用笔记

    1 查看使用的所有端口 netstat ntlp 2 查找文件路径 locate 文件名 如 find 文件名 如 find home 3 Linux下查看和停止所有java进程 在Linux下查看所有java进程命令 ps ef grep
  • 摄像机跟踪主角第三人称的视角

    using UnityEngine using System Collections public class FollowFarget MonoBehaviour public Transform PlayerTransfrom 定义一个
  • Unity 性能优化五:渲染模块压力

    CPU压力 Batching 在GPU渲染前 CPU会把数据按batch发送给GPU 每发送一次 都是一个drawcall GPU在渲染每个batch的时候 会切换渲染状态 这里的渲染状态指的是 影响对象在屏幕上的外观的渲染属性或材质 比如
  • OpenCV自适应阈值化函数adaptiveThreshold

    图像阈值化的一般目的是从灰度图像中分享目标区域和背景区域 然而仅仅通过设定固定阈值很难达到理想的分割效果 在实际应用中 我们可以通过某个像素的邻域以某种方法确定这个像素应该具有的阈值 进而保证图像中各个像素的阈值会随着周期围邻域块的变化而变
  • EasyExcel的简单导出

    EasyExcel的简单导出 Controller层代码 GetMapping download public void download String name HttpServletResponse response fileManag
  • 5、安全理论与框架-企业架构模型(EA)-业务组件模型(IBM CBM)

    一 背景 CBM component business model 组件化业务模型或叫业务组件模型 是IBM在2003年提出的 当时的大背景 公司内 外专业化 CBM是IBM做业务架构的一个重要方法论 就是把业务描述成一个个独立的小块 我们
  • 面试题一:前端去重方法汇总你知道多少?

    题记 我们项目中有很多的业务是需要去重的 那么下面是常用的一些去重的一些方法 用indexOf方法去重 新建一个空数组 遍历需要去重的数组 将数组元素存入新数组中 存放前判断数组中是否已经含有当前元素 没有则存入 此方法也无法对NaN去重
  • 上采样,下采样,过采样,欠采样的区别

    上下是方法 过欠是现象 上采样 upsampling 应该就是内插 补零滤波 下采样 downsampling 应该就是抽取 过采样就是采样频率大于两倍的信号最高频率 欠采样就是采样频率小于两倍的信号最高频率 欠采样失真仅仅是对基带信号而言
  • 源码编译llvm Error 记录

    cmake G Unix Makefiles llvm DLLVM ENABLE PROJECTS bolt clang clang tools extra compiler rt cross project tests libclc l
  • OceanBase:编译、安装和配置手册

    概述 OceanBase是 一个高性能的分布式表格系统 提供类似BigTable的性能和扩展性 但表格中保存的是强类型的数据 比如integer string datetime等 它使用C 编写 运行于64位Linux环境下 生产环境下需要
  • Ubuntu20.04编译安装opencv3.2和opencv_contrib-3.2

    图像特征提取中需要用到SIFT等算法 因此不得不安装从源码编译安装opencv contrib 网上有很多教程 但是在不同的环境下多少会出现一些错误 针对Ubuntu20 04 gcc 7环境下对opencv opencv contrib编
  • ios内嵌h5点击输入框页面放大

    首先咱们这个是基于修改meta没卵用的情况 去修改这个input的style把font size改成16px 我的机型是xr 自己用了反正有效 希望对你有帮助
  • 实战:tomcat版本升级

    tomcat版本升级 由原来的apache tomcat 7 0 96升级到apache tomcat 7 0 109 版本 1 先把原来的备份 mv apache tomcat 7 0 96 1 apache tomcat 7 0 96
  • 01-Kafaka

    1 Kafka 2 的安装与配置 1 上传kafka 2 12 1 0 2 tgz到服务器并解压 tar zxf kafka 2 12 1 0 2 tgz C opt 2 配置环境变量并更新 编辑profile配置文件 vim etc pr
  • 春招大厂面试升级笔记!光CRUD已经不能满足了

    大厂的面试已经升级 早就不满足于CRUD了 今天给大家分享的就是大厂最近升级的面试小 炒 全篇共计为大家详细划分了19个部分 字数超过了20W字 面试题数量超过了1500道 同时结合了大量的实例和代码 涵盖了 Java基础 并发编程 JVM
  • python中sort()和sorted()排序函数用法详解

    python中对数据的排序主要使用sort 和sorted 方法 1 sort 方法 语法结构 列表序列 sort key None reverse False 注意 reverse 表示排序规则 reverse True 降序 rever

随机推荐

  • typora插件_Typora + PicGo 编写博客的神器

    一 软件版本要求 typora 0 9 93 使用最新版本即可 下载链接 https www typora io PicGo 2 2 0以上 也是最好用最新版的 下载链接 https github com Molunerfinn PicGo
  • stable diffusion实践操作-embedding(TEXTUAL INVERSION)

    系列文章目录 本文专门开一节写图生图相关的内容 在看之前 可以同步关注 stable diffusion实践操作 文章目录 系列文章目录 前言 1 embeddding的功能 2 如何去下载 https civitai com models
  • 粽子SHOP-粽子商城官网-一款简洁大气的官网源码

    介绍 一款简洁大气的官网源码 无后台 直接上传服务器或主机即可 可自行编辑内容非常实用的个人介绍页面 大家需要的自行下载 网盘下载地址 http zijieyunpan com OSdKfaj4W2z0 图片
  • FPGA时序分析约束

    时序分析约束 时序分析 时序分析的目的就是通过分析fpga设计各个寄存器之间的数据和时钟传输路径 来分析数据延迟和时钟延迟之间的关系 保证整个系统中的所有寄存器都能正确存储数据 时序约束 两个作用 1 告知EDA软件 该设计需要达到怎么样的
  • 程序员如何逆袭,达到财富自由?

    首先 先给程序员做一个定义 我定义的是 一个普通的程序员 家里普普通通 自己也没在大厂 一个中等公司 拿着两万左右的薪水 年终奖一般发不超过两个月 这样的程序员 逆袭的路有三条 背题 去大厂 混到高P拿股票 劲熬 找到靠谱的创业公司 拿到期
  • Python实现汽车油耗预测_基于Tensorflow2.X

    目录 一 开发环境 二 代码实现 2 1 准备操作 2 1 1 导入所需模块 2 1 2 matplotlib无法正常显示中文的解决方案 若无此情况可跳过 2 2 加载数据集 2 3 数据处理 2 3 1 数据清洗 2 3 2 数据转换 2
  • 学习underscore之比较两个元素是否相同

    underscore1 11 0 中判断两个参数相同的函数为isEqual isEqual 函数认为以下相等 0 与 0 不相等 NaN 与 NaN相等 a i 与 new RegExp a i 相等 5 与 new String 5 相等
  • 【Qt OpenGL教程】10:加载3D世界,并在其中漫游

    第10课 加载3D世界 并在其中漫游 参照NeHe 这次教程中 我将教大家如何加载一个3D世界 并在3D世界中漫游 这相较于我们只能创造一个旋转的立方体或一群星星时有很大的进步了 当然这节课代码难度不低 但也不会很难 只要你跟着我慢慢一步一
  • flutter 生成jks文件 获取sha1

    debug版本 SHA1 C Program Files Java jdk1 8 0 191 bin keytool exe list keystore debug keystore 找到这个目录下的keytool exe 拖进cmd 然后
  • Spring 与 MyBatis 的整合

    1 整合思路 思路 将MyBatis框架中使用到的核心组件配置到Spring容器中 交给Spring来创建和管理 具体来说是将需要自行编码通过SqlSessionFactoryBuilder读取配置文件 构建SqlSessionFactor
  • 【刷题篇】贪心算法(一)

    文章目录 分割平衡字符串 买卖股票的最佳时机 跳跃游戏 钱币找零 分割平衡字符串 class Solution public int balancedStringSplit string s int len s size int cnt 0
  • MAVEN setting.xml

    MAVEN setting xml
  • 【深度学习】 Python 和 NumPy 系列教程(十八):Matplotlib详解:2、3d绘图类型(4)3D曲面图(3D Surface Plot)

    目录 一 前言 二 实验环境 三 Matplotlib详解 1 2d绘图类型 2 3d绘图类型 0 设置中文字体 1 3D线框图 3D Line Plot 2 3D散点图 3D Scatter Plot 3 3D条形图 3D Bar Plo
  • zabbix之自定义监控MySQL主从状态和延迟

    配置环境 监控端 192 168 141 134 zabbix servre zabbix agent Mysql从库 192 168 141 135 zabbix agent mariadb Mysql主库 192 168 141 137
  • 华为德科机试

    一 题型一 共两题 每题100分 难度1颗星 1 一个字符串 首尾相连 计算出现偶数个 o 的字符串最长的长度 例子 alolobo 输出 6 looxdolx 输出 7 bcbcbc 输出 6 import java io Buffere
  • linux 上安装portainer.io

    linux 上安装portainer io 1 portainer io是什么 2 安装 运行镜像 3 登陆 1 portainer io是什么 Portainer是一个轻量级的Docker环境管理UI 可以管理docker host和do
  • Win 7 修改开机密码,使用F8修复提前终止导致蓝屏

    前言 一台win7一体机密码突然不对 也不知道怎么回事就登录不了 使用PE中的NTPWEdit查看修改密码 没有用户列表 步骤 正常启动或者按F8 选择修复 正常电脑如下显示 这种可以直接使用PE改密码 就不放图了 问题电脑如下显示 在修复
  • 《Deep Facial Expression Recognition: A Survey》表情识别综述

    这篇论文是近几年表情识别方向的一篇较好的综述 论文链接 https arxiv org abs 1804 08348 下载链接 https download csdn net download qq 28505705 12678607 论文
  • TensorRT量化-FP16和INT8

    FP16 FP16 FP32 是指 Full Precise Float 32 FP 16 就是 float 16 更省内存空间 更节约推理时间 Half2Mode tensorRT 的一种执行模式 execution mode 这种模式下
  • 实战:SpringBoot集成xxl-sso实现单点登录

    点击上方 Java之间 选择 置顶或者星标 你关注的就是我关心的 前言 单点登录SSO Single Sign On 凡是有一定的开发经验的童鞋都应该有应用或者了解过 小编还是实习生的时候 看到登录某个应用服务后 再跳转其他应用服务 竟然不