xxl-sso 单点登录

news2024/11/17 22:38:08

目录

    • 1 项目启动
      • 修改Host文件
      • 运行路径
      • SSO登录/注销流程验证
    • 2 分析
      • 登录流程

单点登录原理及简单实现:https://www.cnblogs.com/ywlaker/p/6113927.html

xxl-sso是一款基于redis轻量级分布式高可用的SSO实现组件,支持web端(Cookie实现)和app端(Token实现)两种方式,两种方式的验证都是用Filter实现的

项目地址 gitee :https://gitee.com/xuxueli0323/xxl-sso

xxl-sso/ xxl-sso-samples 里面是基于 cookie 和 token 的调用示例,单点登陆Client端接入示例项目

1 项目启动

修改Host文件

修改Host文件:域名方式访问认证中心,模拟跨域与线上真实环境

在host文件中添加以下内容

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

运行路径

分别运行 “xxl-sso-server” 与 “xxl-sso-web-sample-springboot”

1、SSO认证中心地址:
http://xxlssoserver.com:8080/xxl-sso-server
2、Client01应用地址:
http://xxlssoclient1.com:8081/xxl-sso-web-sample-springboot/
3、Client02应用地址:
http://xxlssoclient2.com:8081/xxl-sso-web-sample-springboot/

SSO登录/注销流程验证

正常情况下,登录流程如下:

  1. 访问 “Client01应用地址” ,将会自动 redirect 到 “SSO认证中心地址” 登录界面
  2. 成功登录后,将会自动 redirect 返回到 “Client01应用地址”,并切换为已登录状态
  3. 此时,访问 “Client02应用地址”,不需登陆将会自动切换为已登录状态

正常情况下,注销流程如下:

  1. 访问 “Client01应用地址” 配置的 “注销登陆path”,将会自动 redirect 到 “SSO认证中心地址” 并自动注销登陆状态
  2. 此时,访问 “Client02应用地址”,也将会自动注销登陆状态

2 分析

登录流程

首次访问 client1 的 http://xxlssoclient1.com:8081/xxl-sso-web-sample-springboot/ ,进入过滤器

① 在client项目中配置了core的过滤器XxlSsoWebFilter(判断cookie或者请求携带参数中的id是否与redis中一致),首次访问client1时,过滤器判断cookie、请求携带参数、redis均为null,请求重定向到认证中心server携带参数(login?redirect_url=)

在client项目中配置了core的过滤器XxlSsoWebFilter

@Bean
public FilterRegistrationBean xxlSsoFilterRegistration() {

   JedisUtil.init(xxlSsoRedisAddress);
   FilterRegistrationBean registration = new FilterRegistrationBean();

   registration.setName("XxlSsoWebFilter");
   registration.setOrder(1);
   registration.addUrlPatterns("/*");
   registration.setFilter(new XxlSsoWebFilter());   //配置了 core 里的过滤器
   registration.addInitParameter(Conf.SSO_SERVER, xxlSsoServer);
   registration.addInitParameter(Conf.SSO_LOGOUT_PATH, xxlSsoLogoutPath);
   registration.addInitParameter(Conf.SSO_EXCLUDED_PATHS, xxlSsoExcludedPaths);

   return registration;
}

core 里的过滤器如下

在这里插入图片描述
此处是配置文件中配置的参数

### xxl-sso
## SSO Server认证中心地址(推荐以域名方式配置认证中心,本机可参考章节"2.5"修改host文件配置域名指向)
xxl.sso.server=http://xxlssoserver.com:8080/xxl-sso-server
## 注销登陆path,值为Client端应用的相对路径
xxl.sso.logout.path=/logout
## 路径排除Path,允许设置多个,且支持Ant表达式。用于排除SSO客户端不需要过滤的路径
xxl-sso.excluded.paths=
xxl.sso.redis.address=redis://127.0.0.1:6379
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    HttpServletRequest req = (HttpServletRequest) request;
    HttpServletResponse res = (HttpServletResponse) response;

    // 当前访问的路径为 servletPath="/" 
    String servletPath = req.getServletPath();

    // excluded path check ———— excludedPaths="" 跳过
    if (excludedPaths!=null && excludedPaths.trim().length()>0) {
        for (String excludedPath:excludedPaths.split(",")) {
            String uriPattern = excludedPath.trim();
            // 支持ANT表达式
            if (antPathMatcher.match(uriPattern, servletPath)) {
                // excluded path, allow
                chain.doFilter(request, response);
                return;
            }
        }
    }

    // logout path check ———— logoutPath="/logout" 跳过
    if (logoutPath!=null
            && logoutPath.trim().length()>0
            && logoutPath.equals(servletPath)) {
        // remove cookie
        SsoWebLoginHelper.removeSessionIdByCookie(req, res);
        // redirect logout
        //注销时,请求重定向 http://xxlssoserver.com:8080/xxl-sso-server/logout
        String logoutPageUrl = ssoServer.concat(Conf.SSO_LOGOUT);
        res.sendRedirect(logoutPageUrl);
        return;
    }

    // valid login user, cookie + redirect 此处是判断redis中是否有user,分别以cookieId和请求参数id作为key判断,此时两种key都是null ———— 跳过
    XxlSsoUser xxlUser = SsoWebLoginHelper.loginCheck(req, res);
    // valid login fail 首次登录
    if (xxlUser == null) {
        String header = req.getHeader("content-type");
        boolean isJson=  header!=null && header.contains("json");
        if (isJson) {

            // json msg
            res.setContentType("application/json;charset=utf-8");
            res.getWriter().println("{\"code\":"+Conf.SSO_LOGIN_FAIL_RESULT.getCode()+", \"msg\":\""+ Conf.SSO_LOGIN_FAIL_RESULT.getMsg() +"\"}");
            return;
        } else {
            // total link
            String link = req.getRequestURL().toString();
            // redirect logout
            String loginPageUrl = ssoServer.concat(Conf.SSO_LOGIN)
                    + "?" + Conf.REDIRECT_URL + "=" + link;
            //首次登录 loginPageUrl = http://xxlssoserver.com:8080/xxl-sso-server/login?redirect_url=http://xxlssoclient1.com:8081/xxl-sso-web-sample-springboot/
            res.sendRedirect(loginPageUrl);
            return;
        }
    }
    // ser sso user
    request.setAttribute(Conf.SSO_USER, xxlUser);
    chain.doFilter(request, response);
    return;
}

判断redis中是否有user

public static XxlSsoUser loginCheck(HttpServletRequest request, HttpServletResponse response){
    String cookieSessionId = CookieUtil.getValue(request, "xxl_sso_sessionid");

    // cookie user 此处是通过cookieId获取 redis 中的user
    //首次访问client、server,cookieSessionId为null  xxlUser为null
    //二次认证中心登录后跳回访问client1,所以cookieSessionId为null  xxlUser为null
    //三次client2访问发现携带cookie
    XxlSsoUser xxlUser = SsoTokenLoginHelper.loginCheck(cookieSessionId);
    if (xxlUser != null) {
        return xxlUser;
    }

    // remove old cookie
    //版本不一致,移除session,设置新的
    SsoWebLoginHelper.removeSessionIdByCookie(request, response);

    // set new cookie 此处是通过请求参数的 Id 获取 redis 中的user
    //首次访问client、server,paramSessionId cookieSessionId xxlUser 都为 null
    //二次认证中心登录后跳回访问client1,携带参数 ?xxl_sso_sessionid=1000_48c9730ac0164d6b881c568a2b275b19
    String paramSessionId = request.getParameter("xxl_sso_sessionid");
    //从redis获取user与sessionid进行匹配。匹配成功则设置 cookie
    xxlUser = SsoTokenLoginHelper.loginCheck(paramSessionId);
    if (xxlUser != null) {
        CookieUtil.set(response, Conf.SSO_SESSIONID, paramSessionId, false);    // expire when browser close (client cookie)
        return xxlUser;
    }
    return null;
}

② 进入server的WebController的login方法,发现cookie、请求携带参数、redis均为null 。跳转到登录页,输入账号密码,提交server的dologin登录方法,将user存放cookie 存放redis,请求重定向到client1携带参数(?xxl_sso_sessionid=)
③ 再次来到过滤器,此时cookie为null,判断请求携带参数与redis一致,将user存入cookie,放行到IndexController登录成功页面
④ 此时再访问client2,来到过滤器,过滤器判断cookie、请求携带参数、redis均为null,请求重定向到认证中心server携带参数(login?redirect_url=)
⑤ 进入server的WebController的login方法,发现cookie中有user且与redis一致。请求重定向到client2携带参数(?xxl_sso_sessionid=)
⑥ 再次来到过滤器,此时cookie为null,判断请求携带参数与redis一致,将user存入cookie,放行到IndexController登录成功页面

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

[WGAN] Wasserstein GAN

看这个解析讲的也挺好的:令人拍案叫绝的Wasserstein GAN - 知乎 1、背景 GAN的训练是delicate和unstable的。需要定义一个连续的距离,来衡量模型distribution和真实distribution之间的差异。 2、贡献 提出了Wasserstein-GAN,用Earth Mover (…

常用五大类RFID系统,实践领域广泛,加强现代化管理

随着信息技术的不断进步,RFID技术已逐渐成为企业管理及社会服务领域中不可或缺的一种重要技术手段。根据其不同的应用场景,RFID技术广泛应用于药品监管、固定资产管理、仓储管理、智慧工厂和消费服务等领域。本文将从五个方面介绍常用的RFID系统。 一、…

Linux Ubuntu配置Anaconda与Python的方法

本文介绍在Linux Ubuntu操作系统的电脑中,安装Anaconda环境与Python语言的方法。 在之前的文章Win10中Anaconda及Python的下载与安装方法(https://blog.csdn.net/zhebushibiaoshifu/article/details/122642187)中,我们介绍了在Win…

【资料分享】高边、低边晶体管开关及电路解析

高边和低边晶体管开关 电路中,晶体管常常被用来当做开关使用。晶体管用作开关时有两种不同的接线方式:高边(high side)和低边(low side)。 高边和低边是由晶体管在电路中的位置决定的。晶体管可以是双极性晶体管(BJT…

云性能测试的主要意义是什么?

云性能测试是一种基于云计算技术的性能测试方法,其通过在云端部署测试环境和测试工具,将测试结果反馈给用户,从而帮助用户评估系统的稳定性、性能和可靠性,那云性能测试的主要意义是什么? 一、作用 云性能测试可以帮助…

测试跳槽一次涨4k,我5年跳了3次...

最近有人说,现在测试岗位初始工资太低了,有些刚刚入行的程序员朋友说自己工资连5位数都没有.....干了好几年也没怎么涨。看看别人动辄月薪1.5到2万,其实我想说也没那么难。 说下如何高效地拿到2万的工资,总体来说,就靠…

了解预测性维护:从哪些方面入手?

预测性维护(Predictive Maintenance)是一种基于数据分析和先进技术的维护策略,旨在提前预测设备故障,并在故障发生之前采取适当的维护措施。相比传统的定期维护或纠正性维护,预测性维护能够降低维护成本、提高设备可用…

在行 | 唱响钢铁冶金行业绿色发展进行曲

在行业现场解析行业难题, 用主题方案创新数智价值。 中国是世界第一钢铁冶金大国,钢铁产量接近全球的一半,高产量也带来了高碳排,仅钢铁行业的碳排量,已占全球钢铁碳排放总量的60%以上,占全国碳排放总量的…

DID-M3D 论文学习

1. 解决了什么问题? 单目 3D 检测成本低、配置简单,对一张 RGB 图像预测 3D 空间的 3D 边框。最难的任务就是预测实例深度,因为相机投影后会丢失深度信息。以前的方法大多直接预测深度,本文则指出 RGB 图像上的实例深度不是一目了…

从《流浪地球2》看多团队任务管理

《流浪地球2》作为春节档热门电影,讲述了地球因为太阳系内其他恒星的影响而不断向外逃离,人类必须采取行动拯救地球和自己的故事,是中国科幻电影的里程碑式影片。影片中充满各种科技元素,令人印象深刻,量子计算机550系…

【libcurl 】win32 构建 Release版本 修改cmakelist 链接openssl1.1.*

以下库均已MD的构建以vs2019 V142构建MD构建 直接换用了一个openssl库,libcurl连接报错 $(ProjectDir)..\..\..\3rdparty\openssl\xdw_openssl1_1_1\lib\win32\libcrypto.lib

Seata-go TCC 设计与实现

作者:刘月财 本文主要介绍 seata-go 中 TCC 的设计思路、异常处理以及在实战中的使用。 Seata 是一款开源的分布式事务解决方案,致力于为现代化微服务架构下的分布式事务提供高性能和简单易用的分布式事务服务。Seata 将为用户提供了 AT、TCC、SAGA 和…

IS日志文件存在哪里? Windows服务器lIS日志存放位置及查看

用户每打开一次网页,iis,都会记录用户IP、访问的网页地址、访问时间、访问状态等信息,这些信息保存在iis日志文件里,方便网站管理员掌握网页被访问情况和iis 服务器运行情况。如果网页被恶意访问(如注入数据库),日志中会有相应的记…

C++ 仿函数(二)

在上一篇里我们讲了仿函数是什么,以及一元谓词,二元谓词的概念 C 仿函数(一)_小梁今天敲代码了吗的博客-CSDN博客 这篇是讲“内建函数对象”主要包括:“算术仿函数”,“关系仿函数”,“逻辑仿函数” 目录 一.算术仿…

6年自动化测试经验,终于进字节跳动了,年薪30w其实也并非遥不可及

一些碎碎念 什么都做了,和什么都没做其实是一样的,走出“瞎忙活”的安乐窝,才是避开弯路的最佳路径。希望我的经历能帮助到有需要的朋友。 在测试行业已经混了5个年头了,以前经常听到开发对我说,天天的点点点有意思没…

LC-1373. 二叉搜索子树的最大键值和(后序遍历)

1373. 二叉搜索子树的最大键值和 难度困难173 给你一棵以 root 为根的 二叉树 ,请你返回 任意 二叉搜索子树的最大键值和。 二叉搜索树的定义如下: 任意节点的左子树中的键值都 小于 此节点的键值。任意节点的右子树中的键值都 大于 此节点的键值。任…

IP协议详解之IP地址要领

整个的因特网就是一个单一的、抽象的网络。而IP地址就是给因特网上的每一个主机(或路由器)的每一个接口分配一个在全世界范围是唯一的32位的标识符。IP地址的结构使我们可以在因特网上很方便地进行寻址。但是,根据TCP/IP协议的规定的IP地址是…

【Flutter 工程】002-代码生成:Freezed ——类似 Java 的 lombok

【Flutter 工程】002-代码生成:Freezed ——类似 Java 的 lombok 文章目录 【Flutter 工程】002-代码生成:Freezed ——类似 Java 的 lombok一、概述1、简介2、主要功能3、主页与使用前后比较主页使用前使用后 二、基本使用1、安装2、改造 main.dart3、创…

pygam第4课——颜色监测(迷宫小游戏)

前言:前三节课我们学习了,窗口的创建、图片的加载、常用鼠标事件的等。今天我们学一个颜色的监测,并自制一个迷宫小游戏。那我们一下来看看吧 前面的三节课在这里,大家记得关注收藏一下: 视频演示 1、界面搭建 背景图…

开发者关系工程师如何帮助开发者在Sui上构建

近期,我们与Sui开发者关系负责人Brian Hennessey-Hsien进行了对话,就Sui上的开源、去中心化和开发者成就等话题展开讨论。 日前,我们采访了Sui基金会的开发者关系负责人Brian Hennessey-Hsieh,共同探讨了其对于Web3中开发者发展历…