使用xxl

您所在的位置:网站首页 单点教程 使用xxl

使用xxl

2023-11-22 19:20| 来源: 网络整理| 查看: 265

XXL-SSO 是一个分布式单点登录框架。只需要登录一次就可以访问所有相互信任的应用系统。 拥有"轻量级、分布式、跨域、Cookie+Token均支持、Web+APP均支持"等特性。 以下是它的github地址以及文档地址。

话不多说,先将该项目的代码从github上clone下来。

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

代码整体结构如下 在这里插入图片描述 如图中所示,xxl-sso-core是整个项目的核心,是由它来实现整个单点登录的过程,XxlSsoWebFilter,代码如下:

package com.xxl.sso.core.filter; import com.xxl.sso.core.conf.Conf; import com.xxl.sso.core.entity.ReturnT; import com.xxl.sso.core.login.SsoTokenLoginHelper; import com.xxl.sso.core.path.impl.AntPathMatcher; import com.xxl.sso.core.user.XxlSsoUser; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import javax.servlet.*; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; /** * app sso filter * * @author xuxueli 2018-04-08 21:30:54 */ public class XxlSsoTokenFilter extends HttpServlet implements Filter { private static Logger logger = LoggerFactory.getLogger(XxlSsoTokenFilter.class); private static final AntPathMatcher antPathMatcher = new AntPathMatcher(); private String ssoServer; private String logoutPath; private String excludedPaths; @Override public void init(FilterConfig filterConfig) throws ServletException { ssoServer = filterConfig.getInitParameter(Conf.SSO_SERVER); logoutPath = filterConfig.getInitParameter(Conf.SSO_LOGOUT_PATH); excludedPaths = filterConfig.getInitParameter(Conf.SSO_EXCLUDED_PATHS); logger.info("XxlSsoTokenFilter init."); } @Override public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; // make url String servletPath = req.getServletPath(); // excluded path check 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 filter if (logoutPath!=null && logoutPath.trim().length()>0 && logoutPath.equals(servletPath)) { // logout SsoTokenLoginHelper.logout(req); // response res.setStatus(HttpServletResponse.SC_OK); res.setContentType("application/json;charset=UTF-8"); res.getWriter().println("{\"code\":"+ReturnT.SUCCESS_CODE+", \"msg\":\"\"}"); return; } // login filter XxlSsoUser xxlUser = SsoTokenLoginHelper.loginCheck(req); if (xxlUser == null) { // response res.setStatus(HttpServletResponse.SC_OK); 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; } // ser sso user request.setAttribute(Conf.SSO_USER, xxlUser); // already login, allow chain.doFilter(request, response); return; } }

excludedPaths用于实现将不需要被拦截的请求路径排除在外,在访问时不会被这个filter所拦截,XxlSsoWebFilter是基于cookie实现的,即在登录认证中心时,会将XxlSsoUser这个对象存入到cookie中,再由这里去判断是否在cookie中存在该对象,存在则放行。还有一种是基于token实现的,大致原理和cookie实现的一致。 xxl-sso-server,即它的服务端,它功能的核心主要在WebController/AppController下,分别代表cookie和token这两种单点登录模式,代码如下所示:

package com.xxl.sso.server.controller; import com.xxl.sso.core.conf.Conf; import com.xxl.sso.core.login.SsoWebLoginHelper; import com.xxl.sso.core.store.SsoLoginStore; import com.xxl.sso.core.user.XxlSsoUser; import com.xxl.sso.core.store.SsoSessionIdHelper; import com.xxl.sso.server.core.model.UserInfo; import com.xxl.sso.server.core.result.ReturnT; import com.xxl.sso.server.service.UserService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.servlet.mvc.support.RedirectAttributes; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.UUID; /** * sso server (for web) * * @author xuxueli 2017-08-01 21:39:47 */ @Controller public class WebController { @Autowired private UserService userService; @RequestMapping("/") public String index(Model model, HttpServletRequest request, HttpServletResponse response) { // login check XxlSsoUser xxlUser = SsoWebLoginHelper.loginCheck(request, response); if (xxlUser == null) { return "redirect:/login"; } else { model.addAttribute("xxlUser", xxlUser); return "index"; } } /** * Login page * * @param model * @param request * @return */ @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:/"; } } model.addAttribute("errorMsg", request.getParameter("errorMsg")); model.addAttribute(Conf.REDIRECT_URL, request.getParameter(Conf.REDIRECT_URL)); return "login"; } /** * Login * * @param request * @param redirectAttributes * @param username * @param password * @return */ @RequestMapping("/doLogin") public String doLogin(HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes, String username, String password, String ifRemember) { boolean ifRem = (ifRemember!=null&&"on".equals(ifRemember))?true:false; // valid login ReturnT result = userService.findUser(username, password); if (result.getCode() != ReturnT.SUCCESS_CODE) { redirectAttributes.addAttribute("errorMsg", result.getMsg()); redirectAttributes.addAttribute(Conf.REDIRECT_URL, request.getParameter(Conf.REDIRECT_URL)); return "redirect:/login"; } // 1、make xxl-sso user XxlSsoUser xxlUser = new XxlSsoUser(); xxlUser.setUserid(String.valueOf(result.getData().getUserid())); xxlUser.setUsername(result.getData().getUsername()); xxlUser.setVersion(UUID.randomUUID().toString().replaceAll("-", "")); xxlUser.setExpireMinute(SsoLoginStore.getRedisExpireMinute()); 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); // 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:/"; } } /** * Logout * * @param request * @param redirectAttributes * @return */ @RequestMapping(Conf.SSO_LOGOUT) public String logout(HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes) { // logout SsoWebLoginHelper.logout(request, response); redirectAttributes.addAttribute(Conf.REDIRECT_URL, request.getParameter(Conf.REDIRECT_URL)); return "redirect:/login"; } }

其中一共提供了4个接口,第一个不用多说,很简单,从cookie中获取user,存在则放行,不存在则重定向到登录页面。第二个接口"/login",和第一个很类似,唯一不同的是从请求上下文中获取的重定向的url,由此可判断这个接口应该是提供给客户端用的,单点成功则重定向到指定页面,不成功则返回登录界面。第三个接口"/doLogin",是登录接口,从代码中判断是控制登录逻辑的,使用者可以在这个接口中自定义登录逻辑,满足条件的时候生成XxoUser对象,并以此生成sessionId,并存入cookie中,最后放行。最后一个是登出接口,登出时清除cookie和redis中存放的sessionId,即登录态取消。以下是server端的配置文件,没有什么特别的地方,唯一注意的就是redis带密码时候的配置写法。

### web server.port=8080 server.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 xxl.sso.redis.address=redis://xxl-sso:[email protected]:6379/0 xxl.sso.redis.expire.minute=1440

启动前需要修改logback.xml中生成日志的地址,否则启动会报错。 之后启动xxl-sso-samples下的xxl-sso-web-sample-springboot,同样是修改配置文件和logback.xml。这个项目下主要就是你想被单点访问到的地址。在XxlSsoConfig中注入了一个bean,叫xxlSsoFilterRegistration,这个主要是将核心包下的filter过滤器加入进来,实现拦截请求,重定向到认证中心去登录。

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

启动项目,访问http://localhost:8081/xxl-sso-web-sample-springboot/ 在这里插入图片描述 可以看到它被重定向到了认证中心,后面redirect_url是你要实现单点登录的地址。登陆成功,此时我们可以做一个测试,不携带后面的sessionId直接去访问该地址,发现登录态依然存在。由此证明,我们的单点登录demo已经成功了。 在这里插入图片描述 token版的中心思想和cookie版的基本一致,只是在登录成功后会生成一个token秘钥,并存放在redis中,单点登录时,在header中增加该凭证即可单点成功。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3