推荐一个分布式单点登录框架XXL(shiro分布式单点登录)

  本篇文章为你整理了推荐一个分布式单点登录框架XXL(shiro分布式单点登录)的详细内容,包含有单点登录和分布式session shiro分布式单点登录 分布式登录怎么做 分布式登陆 推荐一个分布式单点登录框架XXL,希望能帮助你了解 推荐一个分布式单点登录框架XXL。

  一文读懂 JWT!

  看完这篇不能再说不懂SSO原理了!

  如果说XXL-JOB你可能并不陌生,它是非常火爆的一个分布式任务调度平台。但其实在该作者还有一个非常优秀的开源项目叫XXL-SSO,这两个个项目都是1000+Star。

  

XXL-SSO 是一个分布式单点登录框架。只需要登录一次就可以访问所有相互信任的应用系统。 拥有"轻量级、分布式、跨域、Cookie+Token均支持、Web+APP均支持"等特性。现已开放源代码,开箱即用。

 

  

 

  这里主要是通过对XXL-SSO源码的分析,将理论和实践结合!

  一、快速接入sso

  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客户端不需要过滤的路径

  JDK:1.7+

  Redis:4.0+

  3、 源码地址

  github: https://github.com/xuxueli/xxl-sso

  gitee: https://gitee.com/xuxueli0323/xxl-sso

  4、 项目结构说明

  

- 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被禁

  

 

  5、 架构图

  应用系统:sso-web系统(8081端口)、sso-web系统(8082端口)(需要登录的系统)

  SSO客户端:登录、退出(独立jar包给应用系统引用)

  SSO服务端:登录(登录服务)、登录状态(提供登录状态校验/登录信息查询的服务)、退出(用户注销服务)

  数据库:存储用户账户信息(一般使用Mysql,在当前项目中为了简便并没有查询数据库)

  缓存:存储用户的登录信息(使用Redis)

  二、快速接入XXL-SSO框架

  1、 部署认证中心(sso-server)

  只需要修改配置文件即可,配置文件位置:application.properties

  

## 配置redis

 

  xxl.sso.redis.address=redis://118.31.224.65:6379

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

  xxl.sso.redis.expire.minute=1440

  

 

  2、 部署单点登陆Client端接入示例项目

  这里指需要接入SSO的系统,在当前项目有xxl-sso-web-sample-springboot和 xxl-sso-token-sample-springboot两个示例项目,这里暂且以sso-web为示例。

  1)、maven依赖

  

 dependency 

 

   groupId com.xuxueli /groupId

   artifactId xxl-sso-core /artifactId

   version ${最新稳定版} /version

   /dependency

  

 

  2)配置 XxlSsoFilter

  参考代码:com.xxl.sso.sample.config.XxlSsoConfig

  

@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 XxlSsoWebFilter());

   registration.addInitParameter(Conf.SSO_SERVER, xxlSsoServer);

   registration.addInitParameter(Conf.SSO_LOGOUT_PATH, xxlSsoLogoutPath);

   return registration;

  

 

  application.properties修改

  

## 中央认证服务地址

 

  xxl.sso.server=http://ssoserver.com:8080/xxl-sso-server

  ## 退出接口

  xxl.sso.logout.path=/logout

  ## 排除走sso的接口

  xxl-sso.excluded.paths=/excludedUrl

  ## redis地址

  xxl.sso.redis.address=redis://118.11.214.65:6379

  

 

  三、快速验证

  1、修改host文件

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

  

127.0.0.1 ssoserver.com

 

  127.0.0.1 webb.com

  127.0.0.1 weba.com

  

 

  2、启动项目

  分别运行 “xxl-sso-server” 与 “xxl-sso-web-sample-springboot”,为了验证单点登录,这里sso-web需求启动两次,只是一次是8081端口,一次是8082端口。

  

## 1、SSO认证中心地址:

 

  http://ssoserver.com:8080/xxl-sso-server

  ## 2、Client01应用地址:

  http://weba.com:8081/xxl-sso-web-sample-springboot/

  ## 3、Client02应用地址:

  http://webb.com:8082/xxl-sso-web-sample-springboot/

  

 

  SSO登录流程

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

  1、访问 "Client01应用地址" ,将会自动 redirect 到 "SSO认证中心地址" 登录界面

  2、成功登录后,将会自动 redirect 返回到 "Client01应用地址",并切换为已登录状态

  3、此时,访问 "Client02应用地址",不需登陆将会自动切换为已登录状态

  很明显Client01登录成功后,Client02无需再重新登录就可以访问了。

  SSO注销流程

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

  

1、访问 "Client01应用地址" 配置的 "注销登陆path",将会自动 redirect 到 "SSO认证中心地址" 并自动注销登陆状态

 

  2、此时,访问 "Client02应用地址",也将会自动注销登陆状态

  

 

  四、核心代码分析

  1、SSO客户端(sso-core)拦截器

  主要看sso拦截器流程就可以了

  

 @Override

 

   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

   HttpServletRequest req = (HttpServletRequest) request;

   HttpServletResponse res = (HttpServletResponse) response;

   // 获取当前请求接口

   String servletPath = req.getServletPath();

   // 1、是否是排除 不走sso的接口 如果是直接放行

   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;

   // 2、是否是退出登录接口

   if (logoutPath != null

   logoutPath.trim().length() 0

   logoutPath.equals(servletPath)) {

   // 2.1删除当前请求客户端的cookie

   SsoWebLoginHelper.removeSessionIdByCookie(req, res);

   // 2.2重定向到sso认证服务的 退出接口

   String logoutPageUrl = ssoServer.concat(Conf.SSO_LOGOUT);

   res.sendRedirect(logoutPageUrl);

   return;

   // 3、校验用户(是否存在,是否过期) 这个方法下面在展开

   XxlSsoUser xxlUser = SsoWebLoginHelper.loginCheck(req, res);

   // 4、令牌校验失败

   if (xxlUser == null) {

   //获取当前请求地址

   String link = req.getRequestURL().toString();

   // 重定向到sso认证服务的 登录接口

   String loginPageUrl = ssoServer.concat(Conf.SSO_LOGIN)

   + "?" + Conf.REDIRECT_URL + "=" + link;

   res.sendRedirect(loginPageUrl);

   return;

   // ser sso user

   request.setAttribute(Conf.SSO_USER, xxlUser);

   // 已经登录 放行

   chain.doFilter(request, response);

   return;

  

 

  在看下上面的loginCheck方法

  

 /**

 

   * 令牌校验

   * @return 用户信息

   public static XxlSsoUser loginCheck(HttpServletRequest request, HttpServletResponse response){

   //去cookie去获取xxl_sso_sessionid 其实就是之前原理篇说的token,只是名称叫法不同

   String cookieSessionId = CookieUtil.getValue(request, Conf.SSO_SESSIONID);

   // 这里去redis中获取用户信息 有可能获取不到。这个方法就不粘贴了 这里有三种情况

   //1、cookieSessionId为空 那么直接返回null

   //2、cookieSessionId不为空,但在redis获取不到用户信息,因为存在其它系统退出后 redis删除了

   //3、redis获取到了用户信息,但超过有效期了 依旧返回null

   XxlSsoUser xxlUser = SsoTokenLoginHelper.loginCheck(cookieSessionId);

   if (xxlUser != null) {

   return xxlUser;

   // 如果获取不到 所以已经在其它系统退出登录了 那删除cookie中的xxl_sso_sessionid

   SsoWebLoginHelper.removeSessionIdByCookie(request, response);

   //如果是 sso登录成功后 回调过来的 这个时候在这里是可以获取到xxl_sso_sessionid的

   String paramSessionId = request.getParameter(Conf.SSO_SESSIONID);

   xxlUser = SsoTokenLoginHelper.loginCheck(paramSessionId);

   if (xxlUser != null) {

   CookieUtil.set(response, Conf.SSO_SESSIONID, paramSessionId, false); /

   return xxlUser;

   return null;

  

 

  2、认证服务器(sso-server)登录接口

  

 /**

 

   * sso认证中心 登录接口

   @RequestMapping(Conf.SSO_LOGIN)

   public String login(Model model, HttpServletRequest request, HttpServletResponse response) {

   // 同样的 该判断sso上有没有全局会话

   XxlSsoUser xxlUser = SsoWebLoginHelper.loginCheck(request, response);

   //如果 其它系统登录成功过 这个就不回为null 直接再带上xxl_sso_sessionid=xxx 重定向到之前接口

   //也不用在登录了

   if (xxlUser != null) {

   // success redirect

   String redirectUrl = request.getParameter(Conf.REDIRECT_URL);

   if (redirectUrl!=null redirectUrl.trim().length() 0) {

   String sessionId = SsoWebLoginHelper.getSessionIdByCookie(request);

   String redirectUrlFinal = redirectUrl + "?" + Conf.SSO_SESSIONID + "=" + sessionId;;

   return "redirect:" + redirectUrlFinal;

   } else {

   return "redirect:/";

   //只有全局会话不存在 才会跳转登录页面

   model.addAttribute("errorMsg", request.getParameter("errorMsg"));

   model.addAttribute(Conf.REDIRECT_URL, request.getParameter(Conf.REDIRECT_URL));

   return "login";

  

 

  3、认证服务器(sso-server)退出接口

  

 @RequestMapping(Conf.SSO_LOGOUT)

 

   public String logout(HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes) {

   // 退出操作

   SsoWebLoginHelper.logout(request, response);

   // 跳转到登录页

   redirectAttributes.addAttribute(Conf.REDIRECT_URL, request.getParameter(Conf.REDIRECT_URL));

   return "redirect:/login";

  

 

  再来看下 logout 方法做了哪些事情

  

 public static void logout(HttpServletRequest request,

 

   HttpServletResponse response) {

   String cookieSessionId = CookieUtil.getValue(request, Conf.SSO_SESSIONID);

   if (cookieSessionId==null) {

   return;

   //1、删除全局缓存 redis中 清除cookieSessionId,这样其它系统在令牌校验的时候 会失败。即一处退出,处处退出。

   String storeKey = SsoSessionIdHelper.parseStoreKey(cookieSessionId);

   if (storeKey != null) {

   SsoLoginStore.remove(storeKey);

   //2、清除全局会话

   CookieUtil.remove(request, response, Conf.SSO_SESSIONID);

  

 

  整个核心代码的逻辑都在这里了,其实结合上一篇的理论篇,理解起来就一点也不复杂了。

  声明: 公众号如需转载该篇文章,发表文章的头部一定要 告知是转至公众号: 后端元宇宙。同时也可以问本人要markdown原稿和原图片。其它情况一律禁止转载!

  以上就是推荐一个分布式单点登录框架XXL(shiro分布式单点登录)的详细内容,想要了解更多 推荐一个分布式单点登录框架XXL的内容,请持续关注盛行IT软件开发工作室。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: