04 Jeesite4.x 前后端分离如何确保是同一会话 您所在的位置:网站首页 jeesite收费吗 04 Jeesite4.x 前后端分离如何确保是同一会话

04 Jeesite4.x 前后端分离如何确保是同一会话

2024-01-01 16:04| 来源: 网络整理| 查看: 265

1 概述

前端使用VUE框架开发,后端U-WEB使用Jeesite4.X开发,U-WEB集成CAS登陆。期望如下:

前后端使用同一会话,方便数据共享;前端只需要访问后端的接口,后端实现登陆后,跳转到前端界面并带上登陆信息。至于后端如何登陆,前端不需要关心。 2 解决方案 3 代码案例

本案例基于Jeesite4.X专业版实现。

3.1 前端登录接口

该方法获取登录用户信息,并携带用户信息,重定向到前端界面。 为了不改变原Jeesite4.X框架登录逻辑,需要强制重定向的界面需要携带参数isUerRedirect=true;

3.2 后端拦截前端请求

后端会拦截该请求,如果未登陆,后端跳转到CAS进行登录,登录成功后跳转到3.1所在方法。 第一步,重写UserFilter,记录登录前地址; 第二步,重写LoginController,获取登录前地址,重定向到该地址; 注:标红部分为重写部分

3.2.1 重写UserFilter /** * Copyright (c) 2013-Now http://jeesite.com All rights reserved. */ package com.jeesite.common.shiro.filter; import org.apache.shiro.web.util.WebUtils; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import java.io.IOException; /** * 用户权限过滤器 * @author ThinkGem * @version 2017-03-22 */ public class UserFilter extends org.apache.shiro.web.filter.authc.UserFilter { @Override protected void redirectToLogin(ServletRequest request, ServletResponse response) throws IOException { PermissionsAuthorizationFilter.redirectToDefaultPath(request, response); } @Override protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws IOException { //标红1 将request保存起来 WebUtils.saveRequest(request); return PermissionsAuthorizationFilter.redirectTo403Page(request, response); } } 3.2.2 重写LoginController /** * Copyright (c) 2013-Now http://jeesite.com All rights reserved. */ package com.jeesite.modules.sys.web; import com.fasterxml.jackson.annotation.JsonView; import com.jeesite.common.config.Global; import com.jeesite.common.lang.StringUtils; import com.jeesite.common.shiro.filter.FormAuthenticationFilter; import com.jeesite.common.shiro.realm.LoginInfo; import com.jeesite.common.web.BaseController; import com.jeesite.common.web.CookieUtils; import com.jeesite.common.web.http.ServletUtils; import com.jeesite.modules.sys.entity.Menu; import com.jeesite.modules.sys.entity.User; import com.jeesite.modules.sys.utils.PwdUtils; import com.jeesite.modules.sys.utils.UserUtils; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.annotation.RequiresPermissions; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.filter.AccessControlFilter; import org.apache.shiro.web.util.SavedRequest; import org.apache.shiro.web.util.WebUtils; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.util.List; /** * 登录Controller * @author ThinkGem * @version 2020-4-13 */ @Controller @RequestMapping(value = "${adminPath}") public class LoginController extends BaseController{ /** * 管理登录 */ @RequestMapping(value = "login", method = RequestMethod.GET) public String login(HttpServletRequest request, HttpServletResponse response, Model model) { // 地址中如果包含JSESSIONID,则跳转一次,去掉JSESSIONID信息。 if (StringUtils.containsIgnoreCase(request.getRequestURI(), ";JSESSIONID=")){ String queryString = request.getQueryString(); queryString = queryString == null ? "" : "?" + queryString; ServletUtils.redirectUrl(request, response, adminPath + "/login" + queryString); return null; } LoginInfo loginInfo = UserUtils.getLoginInfo(); // 如果已经登录,则跳转到管理首页 if(loginInfo != null){ String queryString = request.getQueryString(); queryString = queryString == null ? "" : "?" + queryString; ServletUtils.redirectUrl(request, response, adminPath + "/index" + queryString); return null; } // 如果是登录操作,跳转到此,则认为是登录失败(支持GET登录时传递__login=true参数) if (WebUtils.isTrue(request, "__login")){ return loginFailure(request, response, model); } // 获取登录数据 model.addAllAttributes(FormAuthenticationFilter.getLoginData(request, response)); // 如果是Ajax请求,返回Json字符串。 if (ServletUtils.isAjaxRequest((HttpServletRequest)request)){ model.addAttribute("message", text("sys.login.notLongIn")); return ServletUtils.renderObject(response, model); } // 返回指定用户类型的登录页视图 String userType = (String)model.asMap().get(ServletUtils.EXT_PARAMS_PREFIX + "userType"); if (StringUtils.isBlank(userType)){ userType = User.USER_TYPE_EMPLOYEE; } String view = UserUtils.getUserTypeValue(userType, "loginView"); if(StringUtils.isNotBlank(view)){ return view; } return "modules/sys/sysLogin"; } /** * 登录失败,真正登录的POST请求由Filter完成 */ @RequestMapping(value = "login", method = RequestMethod.POST) public String loginFailure(HttpServletRequest request, HttpServletResponse response, Model model) { LoginInfo loginInfo = UserUtils.getLoginInfo(); // 如果已经登录,则跳转到管理首页 if(loginInfo != null){ String queryString = request.getQueryString(); queryString = queryString == null ? "" : "?" + queryString; ServletUtils.redirectUrl(request, response, adminPath + "/index" + queryString); return null; } // 获取登录失败数据 model.addAllAttributes(FormAuthenticationFilter.getLoginFailureData(request, response)); // 如果是Ajax请求,返回Json字符串。 if (ServletUtils.isAjaxRequest(request)){ return ServletUtils.renderObject(response, model); } // 返回指定用户类型的登录页视图 String userType = (String)model.asMap().get(ServletUtils.EXT_PARAMS_PREFIX + "userType"); if (StringUtils.isBlank(userType)){ userType = User.USER_TYPE_EMPLOYEE; } String view = UserUtils.getUserTypeValue(userType, "loginView"); if(StringUtils.isNotBlank(view)){ return view; } return "modules/sys/sysLogin"; } /** * 登录成功,进入管理首页 */ @RequestMapping(value = "index") public String index(HttpServletRequest request, HttpServletResponse response, Model model) { // 地址中如果包含JSESSIONID,则跳转一次,去掉JSESSIONID信息。 if (StringUtils.containsIgnoreCase(request.getRequestURI(), ";JSESSIONID=")){ String queryString = request.getQueryString(); queryString = queryString == null ? "" : "?" + queryString; ServletUtils.redirectUrl(request, response, adminPath + "/index" + queryString); return null; } // 验证下用户权限,以便调用doGetAuthorizationInfo方法,保存单点登录登出句柄 Subject subject = SecurityUtils.getSubject(); if (subject == null || !subject.isPermitted("user")){ if (subject != null){ subject.logout(); } String queryString = request.getQueryString(); queryString = queryString == null ? "" : "?" + queryString; ServletUtils.redirectUrl(request, response, adminPath + "/login" + queryString); return null; } //获取登录用户信息 LoginInfo loginInfo = UserUtils.getLoginInfo(); // 未加载shiro模块时会为空,直接访问则提示操作权限不足。 if(loginInfo == null){ if (subject != null){ subject.logout(); } String queryString = request.getQueryString(); queryString = queryString == null ? "" : "?" + queryString; ServletUtils.redirectUrl(request, response, adminPath + "/login" + queryString); return null; } // 当前用户对象信息 User user = UserUtils.get(loginInfo.getId()); if (user == null){ UserUtils.getSubject().logout(); String queryString = request.getQueryString(); queryString = queryString == null ? "" : "?" + queryString; ServletUtils.redirectUrl(request, response, adminPath + "/login" + queryString); return null; } model.addAttribute("user", user); // 设置当前用户信息 //获取当前会话对象 Session session = UserUtils.getSession(); // 是否是登录操作 boolean isLogin = "true".equals(session.getAttribute("__login")); if (isLogin){ // 获取后接着清除,防止下次获取仍然认为是登录状态 session.removeAttribute("__login"); // 设置共享SessionId的Cookie值(第三方系统使用) String cookieName = Global.getProperty("session.shareSessionIdCookieName"); if (StringUtils.isNotBlank(cookieName)){ CookieUtils.setCookie((HttpServletResponse)response, cookieName, (String)session.getId()); } // 如果登录设置了语言,则切换语言 if (loginInfo.getParam("lang") != null){ Global.setLang(loginInfo.getParam("lang"), request, response); } } // 获取登录成功后跳转的页面 String successUrl = request.getParameter("__url"); if (StringUtils.isBlank(successUrl)){ successUrl = Global.getProperty("shiro.successUrl"); } // 登录操作如果是Ajax操作,直接返回登录信息字符串。 if (ServletUtils.isAjaxRequest(request)){ model.addAttribute("result", Global.TRUE); // 如果是登录,则返回登录成功信息,否则返回获取成功信息 if (isLogin){ model.addAttribute("message", text("sys.login.success")); }else{ model.addAttribute("message", text("sys.login.getInfo")); } model.addAttribute("sessionid", (String)session.getId()); if (!StringUtils.contains(successUrl, "://")){ successUrl = request.getContextPath() + successUrl; } model.addAttribute("__url", successUrl); // 告诉浏览器登录后跳转的页面 return ServletUtils.renderObject(response, model); } // 如果是登录操作,则跳转到登录成功页 else if (isLogin){ //标红2 登录成功后拿出request进行 //强制跳转界面开始 start SavedRequest savedRequest = WebUtils.getAndClearSavedRequest(request); if (savedRequest != null && savedRequest.getMethod().equalsIgnoreCase(AccessControlFilter.GET_METHOD)) { String queryString = savedRequest.getQueryString(); //判断是否是强制跳转界面 if (StringUtils.isNotBlank(queryString) && queryString.contains("isUerRedirect=true")){ String redirectSuccessUrl = savedRequest.getRequestUrl(); String contextPath = request.getContextPath(); //替换请求地址自带的上下文路径 if (!StringUtils.contains(redirectSuccessUrl, "://")){ if (redirectSuccessUrl.startsWith(contextPath)){ redirectSuccessUrl=redirectSuccessUrl.replaceFirst(contextPath,""); } } return REDIRECT + redirectSuccessUrl; } } //强制跳转界面结束 end return REDIRECT + successUrl; } // 是否允许刷新主页,如果已登录,再次访问主页,则退出原账号。 if (!Global.getConfigToBoolean("shiro.isAllowRefreshIndex", "true")){ String logined = CookieUtils.getCookie(request, "LOGINED"); if (StringUtils.isBlank(logined) || "false".equals(logined)){ CookieUtils.setCookie(response, "LOGINED", "true"); }else if (StringUtils.equals(logined, "true")){ UserUtils.getSubject().logout(); CookieUtils.setCookie(response, "LOGINED", "false"); String queryString = request.getQueryString(); queryString = queryString == null ? "" : "?" + queryString; return REDIRECT + adminPath + "/login" + queryString; } } // 初始密码策略和密码修改策略验证(0:关闭;1:提醒用户;2:强制修改初始或旧密码) String passwordModifyUrl = PwdUtils.passwordModifyValid(user, model); if (passwordModifyUrl != null){ try { request.getRequestDispatcher(passwordModifyUrl).forward(request, response); } catch (Exception e) { e.printStackTrace(); } return null; } // 非无类型用户,自动根据用户类型设置默认菜单的归属系统(个性化示例) //if (!User.USER_TYPE_NONE.equals(user.getUserType())){ // session.setAttribute("sysCode", user.getUserType()); // UserUtils.removeCache(UserUtils.CACHE_AUTH_INFO+"_"+session.getId()); //} // 登录切换角色身份(个性化示例) //String roleCode = "dept"; //session.setAttribute("roleCode", roleCode); //UserUtils.removeCache(UserUtils.CACHE_AUTH_INFO+"_"+session.getId()); // 返回指定用户类型的首页视图 String view = UserUtils.getUserTypeValue(user.getUserType(), "indexView"); if(StringUtils.isNotBlank(view)){ return view; } // 返回主页面视图 return "modules/sys/sysIndex"; } /** * 获取侧边栏菜单数据 */ @RequiresPermissions("user") @RequestMapping(value = "index/menuTree") public String indexMenuTree(String parentCode) { return "modules/sys/sysIndex/menuTree"; } /** * 获取当前用户权限字符串数据(移动端用) */ @RequiresPermissions("user") @RequestMapping(value = "authInfo") @ResponseBody public AuthorizationInfo authInfo() { return UserUtils.getAuthInfo(); } /** * 获取当前用户菜单数据(移动端用) */ @RequiresPermissions("user") @RequestMapping(value = "menuTree") @ResponseBody @JsonView(Menu.SimpleView.class) public List menuTree(String parentCode) { return UserUtils.getMenuTreeByParentCode(parentCode); } /** * 切换系统菜单(仅超级管理员有权限) */ @RequiresPermissions("user") @RequestMapping(value = "switch/{sysCode}") public String switchSys(@PathVariable String sysCode) { Session session = UserUtils.getSession(); if (StringUtils.isNotBlank(sysCode)){ session.setAttribute("sysCode", sysCode); }else{ session.removeAttribute("sysCode"); } UserUtils.removeCache(UserUtils.CACHE_AUTH_INFO+"_"+session.getId()); return REDIRECT + adminPath + "/index"; } /** * 切换角色菜单(仅超级管理员有权限) */ @RequiresPermissions("user") @RequestMapping(value = {"switchRole","switchRole/{roleCode}"}) public String switchRole(@PathVariable(required=false) String roleCode) { Session session = UserUtils.getSession(); if (StringUtils.isNotBlank(roleCode)){ session.setAttribute("roleCode", roleCode); }else{ session.removeAttribute("roleCode"); } UserUtils.removeCache(UserUtils.CACHE_AUTH_INFO+"_"+session.getId()); return REDIRECT + adminPath + "/index"; } /** * 切换主题 */ @RequiresPermissions("user") @RequestMapping(value = "switchSkin/{skinName}") public String switchSkin(@PathVariable String skinName, HttpServletRequest request, HttpServletResponse response) { LoginInfo loginInfo = UserUtils.getLoginInfo(); if (StringUtils.isNotBlank(skinName) && !"select".equals(skinName)){ CookieUtils.setCookie(response, "skinName_" + loginInfo.getId(), skinName); return REDIRECT + adminPath + "/index"; } return "modules/sys/switchSkin"; } /** * 个人桌面页面 */ @RequiresPermissions("user") @RequestMapping(value = "desktop") public String desktop(HttpServletRequest request, HttpServletResponse response, Model model) { return "modules/sys/sysDesktop"; } }


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有