0
点赞
收藏
分享

微信扫一扫

XXL-SSO 实现SSO单点登录

一、 概述:

本文旨在使用XXL-SSO开源架构 实现单点登录系统。


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


拥有”轻量级、分布式、跨域、Cookie+Token均支持、Web+APP均支持”等特性。现已开放源代码,开箱即用。


官网地址:分布式单点登录框架XXL-SSO


二、 准备:

下载XXL-SSO

GitHub - xuxueli/xxl-sso: A distributed single-sign-on framework.(分布式单点登录框架XXL-SSO)

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


安装 xxl-sso-core-1.1.0.jar 到maven仓库:


mvn install:install-file -Dfile=D:/yourpath/xxl-sso-core-1.1.0.jar -DgroupId=com.xuxueli -DartifactId=xxl-sso-core -Dversion=1.1.0 -Dpackaging=jar


安装redis、并启动...

执行sql脚本:mysql创建用户表等相关操作,详细参考文末代码

三、实现单点登录服务端:

1)使用架构:


springboot

mybatisPlus  for mysql

swagger

xxl-sso

2)代码参考如下:


pom.xml

       <!-- sso core -->

       <dependency>

           <groupId>com.xuxueli</groupId>

           <artifactId>xxl-sso-core</artifactId>

           <version>1.1.0</version>

       </dependency>

       <!-- jedis -->

       <dependency>

           <groupId>redis.clients</groupId>

           <artifactId>jedis</artifactId>

           <version>2.9.0</version>

       </dependency>

XxlSsoConfig.java

@Configuration

public class XxlSsoConfig implements InitializingBean, DisposableBean {

   @Value("${xxl.sso.redis.address}")

   private String redisAddress;

   @Value("${xxl.sso.redis.expire.minite}")

   private int redisExpireMinite;

   @Override

   public void afterPropertiesSet() throws Exception {

       SsoLoginStore.setRedisExpireMinite(redisExpireMinite);

       SsoTokenLoginHelper.setRedisExpireMinite(redisExpireMinite);

       JedisUtil.init(redisAddress);

   }

   @Override

   public void destroy() throws Exception {

       JedisUtil.close();

   }

}


登录页初始化

   @RequestMapping(Conf.SSO_LOGIN)

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

       // login check

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

       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:/";

           }

       }

       // 查询账套(自定义查询)

       List<TSystemSob> sobs = sysUserService.qrySobLst();

       model.addAttribute("sobs", sobs);

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

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

       return "login";

   }


登录动作

@RequestMapping("/doLogin")

   public String doLogin(HttpServletRequest request,

                         HttpServletResponse response,

                         RedirectAttributes redirectAttributes,

                         @RequestParam String username,

                         @RequestParam String password,

                         @RequestParam Integer sob,

                         String ifRemember) {

       boolean ifRem = (ifRemember != null && "on".equals(ifRemember)) ? true : false;

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

       // valid login

       TSysUser usr = sysUserMapper.qryOne(username, sob);

       if (usr == null) {

           redirectAttributes.addAttribute("errorMsg", "用户不存在!");

           return "redirect:/login";

       }

       if (!Md5Util.isMatchPassword(password.trim(), usr.getPassword())) {

           redirectAttributes.addAttribute("errorMsg", "用户名或密码错误!");

           return "redirect:/login";

       }

       // 1、make xxl-sso user

       XxlSsoUser xxlUser = new XxlSsoUser();

       xxlUser.setUserid(String.valueOf(usr.getAccount()));

       xxlUser.setUsername(usr.getRealName());

       xxlUser.setVersion(UUID.randomUUID().toString().replaceAll("-", ""));

       xxlUser.setExpireMinite(SsoLoginStore.getRedisExpireMinite());

       xxlUser.setExpireFreshTime(System.currentTimeMillis());

       // 2、make session id

       String sessionId = SsoSessionIdHelper.makeSessionId(xxlUser);

       // 3、login, store storeKey + cookie sessionId

       SsoWebLoginHelper.login(response, sessionId, xxlUser, ifRem, redisExpireMinite * 60);

       // 4、return, redirect sessionId

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

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

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

           return "redirect:" + redirectUrlFinal;

       } else {

           return "redirect:/";

       }

   }


退出登录

   @RequestMapping(Conf.SSO_LOGOUT)

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

       // logout

       SsoWebLoginHelper.logout(request, response);

       // del sessionData

       removeStorageData(request);

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

       return "redirect:/login";

   }

登录页面( freemarker模板文件 )

<form action="${request.contextPath}/doLogin">

       <div class="login-box-body">

           <p class="login-box-msg">统一认证中心</p>

           <div class="form-group has-feedback">

               <input type="text" name="username" class="form-control" placeholder="Please input username."

                      value="admin" maxlength="50">

               <span class="glyphicon glyphicon-envelope form-control-feedback"></span>

           </div>

           <div class="form-group has-feedback">

               <input type="password" name="password" class="form-control" placeholder="Please input password."

                      value="123456" maxlength="50">

               <span class="glyphicon glyphicon-lock form-control-feedback"></span>

           </div>

           <div class="form-group">

               <select class="form-control input-s-sm inline" name="sob">

                   <#list sobs as ss>

                   <option value="${ss.id}">${ss.sobName}</option>

                   </#list>

               </select>

           </div>

           <#if errorMsg?exists>

               <p style="color: red;">${errorMsg}</p>

           </#if>

           <div class="row">

               <div class="col-xs-8">

                   <div class="checkbox icheck">

                       <label>

                           <input type="checkbox" name="ifRemember">记住密码

                       </label>

                   </div>

               </div><!-- /.col -->

               <div class="col-xs-4">

                   <input type="hidden" name="redirect_url" value="${redirect_url!''}"/>

                   <button type="submit" class="btn btn-primary btn-block btn-flat">Login</button>

               </div>

           </div>

       </div>

   </form>


四、实现客户端:

配置文件

@Configuration

public class XxlSsoConfig implements DisposableBean {

   @Value("${xxl.sso.server}")

   private String xxlSsoServer;

   @Value("${xxl.sso.logout.path}")

   private String xxlSsoLogoutPath;

   @Value("${xxl.sso.excluded.paths}")

   private String xxlSsoExcludedPaths;

   @Value("${xxl.sso.redis.address}")

   private String xxlSsoRedisAddress;

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

       registration.addInitParameter(Conf.SSO_EXCLUDED_PATHS, xxlSsoExcludedPaths);

       return registration;

   }

   @Override

   public void destroy() throws Exception {

       // xxl-sso, redis close

       JedisUtil.close();

   }

}


首页跳转

   @RequestMapping("/")

   public String index(Model model, HttpServletRequest request) {

       XxlSsoUser xxlUser = (XxlSsoUser) request.getAttribute(Conf.SSO_USER);

       model.addAttribute("xxlUser", xxlUser);

       return "index";

   }

五、启动程序

启动顺序1. SSOServerApp、2.ClientApp


客户端port:8088


服务端port:8086


在浏览器地址栏输入:http://127.0.0.1:8088/client


完成跳转,如图




注:账套为本人自定义信息,可酌情删除。


用户名:admin   、密码:123456


登录成功:




六、备注:

以上即实现了xxl-sso架构的单点登录系统,由于架构较轻量,即功能性单一,不过扩展较方便。


本文在xxl-sso-core核心包中,做了几处简单修改,旨在实现登出跳转,打印log等功能,喜欢扩展的朋友可自行修改。









举报

相关推荐

0 条评论