diff --git a/modules/core/src/main/java/com/jeesite/common/shiro/filter/CasAuthenticationFilter.java b/modules/core/src/main/java/com/jeesite/common/shiro/filter/CasAuthenticationFilter.java index dcb8126e..6a7038ed 100644 --- a/modules/core/src/main/java/com/jeesite/common/shiro/filter/CasAuthenticationFilter.java +++ b/modules/core/src/main/java/com/jeesite/common/shiro/filter/CasAuthenticationFilter.java @@ -3,44 +3,34 @@ */ package com.jeesite.common.shiro.filter; -import java.io.IOException; - -import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse; import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.subject.Subject; import org.apache.shiro.web.util.WebUtils; +import com.jeesite.common.lang.ExceptionUtils; import com.jeesite.common.lang.StringUtils; import com.jeesite.common.shiro.realm.CasAuthorizingRealm; -import com.jeesite.common.shiro.realm.LoginInfo; /** * CAS过滤器 * @author ThinkGem - * @version 2018-7-11 + * @version 2020-9-19 */ @SuppressWarnings("deprecation") public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter { - - private CasAuthorizingRealm authorizingRealm; // 安全认证类 /** * 登录成功调用事件 */ @Override protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception { - - // 登录成功后初始化授权信息并处理登录后的操作 - authorizingRealm.onLoginSuccess((LoginInfo)subject.getPrincipal(), (HttpServletRequest)request); - - // AJAX不支持Redirect改用Forward - request.getRequestDispatcher(getSuccessUrl()).forward(request, response); - return false; + return FormAuthenticationFilter.onLoginSuccess((HttpServletRequest)request, (HttpServletResponse)response); } /** @@ -59,15 +49,15 @@ public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter { return false; } else { try { - if (ae != null && StringUtils.startsWith(ae.getMessage(), "msg:")){ + String message = ExceptionUtils.getExceptionMessage(ae); + if (StringUtils.isNotBlank(message)){ request.setAttribute("exception", ae); + request.setAttribute("message", message); request.getRequestDispatcher("/error/403").forward(request, response); }else{ WebUtils.issueRedirect(request, response, getLoginUrl()); } - } catch (ServletException e) { - e.printStackTrace(); - } catch (IOException e) { + } catch (Exception e) { e.printStackTrace(); } return false; @@ -75,7 +65,7 @@ public class CasAuthenticationFilter extends org.apache.shiro.cas.CasFilter { } public void setAuthorizingRealm(CasAuthorizingRealm authorizingRealm) { - this.authorizingRealm = authorizingRealm; + } } diff --git a/modules/core/src/main/java/com/jeesite/common/shiro/filter/FormAuthenticationFilter.java b/modules/core/src/main/java/com/jeesite/common/shiro/filter/FormAuthenticationFilter.java index 50b3b2cc..22ff08cd 100644 --- a/modules/core/src/main/java/com/jeesite/common/shiro/filter/FormAuthenticationFilter.java +++ b/modules/core/src/main/java/com/jeesite/common/shiro/filter/FormAuthenticationFilter.java @@ -34,7 +34,6 @@ import com.jeesite.common.lang.StringUtils; import com.jeesite.common.network.IpUtils; import com.jeesite.common.shiro.authc.FormToken; import com.jeesite.common.shiro.realm.BaseAuthorizingRealm; -import com.jeesite.common.shiro.realm.LoginInfo; import com.jeesite.common.web.CookieUtils; import com.jeesite.common.web.http.ServletUtils; import com.jeesite.modules.sys.entity.Log; @@ -45,20 +44,20 @@ import com.jeesite.modules.sys.utils.UserUtils; /** * 表单验证(包含验证码)过滤类 * @author ThinkGem - * @version 2020-4-13 + * @version 2020-9-19 */ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc.FormAuthenticationFilter { - public static final String CAPTCHA_PARAM = "validCode"; // 验证码 - public static final String MESSAGE_PARAM = "message"; // 登录返回消息 - public static final String REMEMBER_USERCODE_PARAM = "rememberUserCode"; // 记住用户名 - public static final String EXCEPTION_ATTRIBUTE_NAME = "exception"; // 异常类属性名 + public static final String CAPTCHA_PARAM = "validCode"; // 验证码 + public static final String MESSAGE_PARAM = "message"; // 登录返回消息 + public static final String REMEMBER_USERCODE_PARAM = "rememberUserCode"; // 记住用户名 + public static final String EXCEPTION_ATTRIBUTE_NAME = "exception"; // 异常类属性名 private static final Logger logger = LoggerFactory.getLogger(FormAuthenticationFilter.class); - - private BaseAuthorizingRealm authorizingRealm; // 安全认证类 + private static FormAuthenticationFilter instance; - private Cookie rememberUserCodeCookie; // 记住用户名Cookie + private BaseAuthorizingRealm authorizingRealm; + private Cookie rememberUserCodeCookie; // 记住用户名Cookie /** * 构造方法 @@ -68,8 +67,16 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc. rememberUserCodeCookie = new SimpleCookie(REMEMBER_USERCODE_PARAM); rememberUserCodeCookie.setHttpOnly(true); rememberUserCodeCookie.setMaxAge(Cookie.ONE_YEAR); + instance = this; } + /** + * 创建登录授权令牌 + */ + public static FormToken newToken(HttpServletRequest request, HttpServletResponse response) { + return (FormToken)instance.createToken(request, response); + } + /** * 创建登录授权令牌 */ @@ -100,7 +107,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc. logger.info("登录账号为空或解码错误."); } } - // 登录成功后,判断是否需要记住用户名 + // 登录时判断是否需要记住用户名 if (WebUtils.isTrue(request, REMEMBER_USERCODE_PARAM)) { rememberUserCodeCookie.setValue(EncodeUtils.encodeUrl(EncodeUtils.xssFilter(username))); rememberUserCodeCookie.saveTo((HttpServletRequest)request, (HttpServletResponse)response); @@ -241,30 +248,51 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc. return super.executeLogin(request, response); } + /** + * 登录成功调用事件(静态方便其他位置调用) + */ + public static boolean onLoginSuccess(HttpServletRequest request, HttpServletResponse response) { + try { + return instance.onLoginSuccess(null, null, request, response); + } catch (Exception e) { + e.printStackTrace(); + } + return false; + } + /** * 登录成功调用事件 */ @Override protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception { - // 登录成功后初始化授权信息并处理登录后的操作 - authorizingRealm.onLoginSuccess((LoginInfo)subject.getPrincipal(), (HttpServletRequest) request); - + authorizingRealm.onLoginSuccess(UserUtils.getLoginInfo(), (HttpServletRequest)request); // AJAX不支持Redirect改用Forward - request.getRequestDispatcher(getSuccessUrl()).forward(request, response); + try { + request.getRequestDispatcher(getSuccessUrl()).forward(request, response); + } catch (Exception e) { + e.printStackTrace(); + } return false; } + /** + * 登录失败调用事件(静态方便其他位置调用) + */ + public static boolean onLoginFailure(AuthenticationException e, HttpServletRequest request, HttpServletResponse response) { + return instance.onLoginFailure(null, e, request, response); + } + /** * 登录失败调用事件 */ @Override protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) { String message = StringUtils.EMPTY; - if (e instanceof IncorrectCredentialsException || e instanceof UnknownAccountException) { - message = Global.getText("sys.login.failure"); - } else if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")) { + if (e.getMessage() != null && StringUtils.startsWith(e.getMessage(), "msg:")) { message = StringUtils.replace(e.getMessage(), "msg:", ""); + } else if (e instanceof IncorrectCredentialsException || e instanceof UnknownAccountException) { + message = Global.getText("sys.login.failure"); } else { message = Global.getText("sys.login.error"); logger.error(message, e); // 输出到日志文件 @@ -272,20 +300,20 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc. request.setAttribute(EXCEPTION_ATTRIBUTE_NAME, e); request.setAttribute(MESSAGE_PARAM, message); - // 登录操作如果是Ajax操作,直接返回登录信息字符串。 - if (ServletUtils.isAjaxRequest(((HttpServletRequest) request))){ - Map data = getLoginFailureData(((HttpServletRequest) request), ((HttpServletResponse) response)); - ServletUtils.renderResult(((HttpServletResponse) response), Global.TRUE, message, data); - return false; + // AJAX不支持Redirect改用Forward + try { + String loginFailureUrl = Global.getProperty("adminPath")+"/loginFailure"; + request.getRequestDispatcher(loginFailureUrl).forward(request, response); + } catch (Exception ex) { + ex.printStackTrace(); } - - return true; - } - - public void setAuthorizingRealm(BaseAuthorizingRealm authorizingRealm) { - this.authorizingRealm = authorizingRealm; + return false; } + /** + * 获取登录页面数据 + * @author ThinkGem + */ public static Map getLoginData(HttpServletRequest request, HttpServletResponse response) { Map data = MapUtils.newHashMap(); @@ -294,7 +322,7 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc. for (Entry entry : paramMap.entrySet()){ data.put(ServletUtils.EXT_PARAMS_PREFIX + entry.getKey(), entry.getValue()); } - + // 如果已登录,再次访问主页,则退出原账号。 if (!Global.TRUE.equals(Global.getConfig("shiro.isAllowRefreshIndex"))){ CookieUtils.setCookie(response, "LOGINED", "false"); @@ -316,6 +344,10 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc. return data; } + /** + * 获取登录失败数据 + * @author ThinkGem + */ public static Map getLoginFailureData(HttpServletRequest request, HttpServletResponse response) { Map data = MapUtils.newHashMap(); @@ -362,4 +394,9 @@ public class FormAuthenticationFilter extends org.apache.shiro.web.filter.authc. data.put("result", Global.FALSE); return data; } + + public void setAuthorizingRealm(BaseAuthorizingRealm authorizingRealm) { + this.authorizingRealm = authorizingRealm; + } + } \ No newline at end of file diff --git a/modules/core/src/main/java/com/jeesite/common/shiro/realm/CasAuthorizingRealm.java b/modules/core/src/main/java/com/jeesite/common/shiro/realm/CasAuthorizingRealm.java index cbc07bc2..95d55aab 100644 --- a/modules/core/src/main/java/com/jeesite/common/shiro/realm/CasAuthorizingRealm.java +++ b/modules/core/src/main/java/com/jeesite/common/shiro/realm/CasAuthorizingRealm.java @@ -38,7 +38,7 @@ import com.jeesite.modules.sys.utils.UserUtils; /** * 系统安全认证实现类 * @author ThinkGem - * @version 2018-7-11 + * @version 2020-9-19 */ @SuppressWarnings("deprecation") public class CasAuthorizingRealm extends BaseAuthorizingRealm { @@ -92,7 +92,7 @@ public class CasAuthorizingRealm extends BaseAuthorizingRealm { casToken.setUserId(casPrincipal.getName()); // 生成登录信息对象 - FormToken token = new FormToken(); + FormToken token = new FormToken(request); token.setUsername(casPrincipal.getName()); Map params = MapUtils.newHashMap(); params.putAll(casPrincipal.getAttributes()); diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/LoginController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/LoginController.java index 2848b5e6..7e354878 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/web/LoginController.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/LoginController.java @@ -37,14 +37,14 @@ import com.jeesite.modules.sys.utils.UserUtils; /** * 登录Controller * @author ThinkGem - * @version 2020-4-13 + * @version 2020-9-19 */ @Controller @RequestMapping(value = "${adminPath}") public class LoginController extends BaseController{ /** - * 管理登录 + * 登录页面 */ @RequestMapping(value = "login", method = RequestMethod.GET) public String login(HttpServletRequest request, HttpServletResponse response, Model model) { @@ -94,9 +94,9 @@ public class LoginController extends BaseController{ } /** - * 登录失败,真正登录的POST请求由Filter完成 + * 登录失败,返回错误信息 */ - @RequestMapping(value = "login", method = RequestMethod.POST) + @RequestMapping(value = "loginFailure") public String loginFailure(HttpServletRequest request, HttpServletResponse response, Model model) { LoginInfo loginInfo = UserUtils.getLoginInfo(); @@ -200,6 +200,9 @@ public class LoginController extends BaseController{ // 获取登录成功后跳转的页面 String successUrl = request.getParameter("__url"); + if (StringUtils.isBlank(successUrl)){ + successUrl = (String)request.getAttribute("__url"); + } if (StringUtils.isBlank(successUrl)){ successUrl = Global.getProperty("shiro.successUrl"); } @@ -272,16 +275,16 @@ public class LoginController extends BaseController{ } /** - * 获取侧边栏菜单数据 + * 侧边栏菜单数据 */ @RequiresPermissions("user") @RequestMapping(value = "index/menuTree") public String indexMenuTree(String parentCode) { - return "modules/sys/sysIndex/menuTree"; + return "modules/sys/menuTree"; } /** - * 获取当前用户权限字符串数据(移动端用) + * 当前用户权限字符串数据(移动端用) */ @RequiresPermissions("user") @RequestMapping(value = "authInfo") @@ -291,7 +294,7 @@ public class LoginController extends BaseController{ } /** - * 获取当前用户菜单数据(移动端用) + * 当前用户菜单数据(移动端用) */ @RequiresPermissions("user") @RequestMapping(value = "menuTree") @@ -334,7 +337,7 @@ public class LoginController extends BaseController{ } /** - * 切换主题 + * 切换主题风格 */ @RequiresPermissions("user") @RequestMapping(value = "switchSkin/{skinName}") diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/SsoController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/SsoController.java index 4379b947..ba2ced75 100644 --- a/modules/core/src/main/java/com/jeesite/modules/sys/web/SsoController.java +++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/SsoController.java @@ -18,6 +18,7 @@ import com.jeesite.common.codec.EncodeUtils; import com.jeesite.common.config.Global; import com.jeesite.common.lang.ObjectUtils; import com.jeesite.common.shiro.authc.FormToken; +import com.jeesite.common.shiro.filter.FormAuthenticationFilter; import com.jeesite.common.web.BaseController; import com.jeesite.common.web.http.ServletUtils; import com.jeesite.modules.sys.entity.User; @@ -26,7 +27,7 @@ import com.jeesite.modules.sys.utils.UserUtils; /** * 单点登录Controller * @author ThinkGem - * @version 2017-03-25 + * @version 2020-9-19 */ @Controller public class SsoController extends BaseController{ @@ -63,24 +64,20 @@ public class SsoController extends BaseController{ // 通过令牌登录系统 if (token != null){ try { - FormToken upToken = new FormToken(); - upToken.setUsername(username); // 登录用户名 - upToken.setSsoToken(token); // 单点登录令牌 - upToken.setParams(ServletUtils.getExtParams(request)); // 登录附加参数 - UserUtils.getSubject().login(upToken); - if (ServletUtils.isAjaxRequest(request)){ - return ServletUtils.renderResult(response, Global.TRUE, text("账号登录成功")); - }else{ - return REDIRECT + EncodeUtils.decodeUrl2(url); - } + // FormToken 构造方法的三个参数:登录名、单点登录的令牌秘钥、请求对象 + UserUtils.getSubject().login(new FormToken(username, token, request)); + request.setAttribute("__url", EncodeUtils.decodeUrl2(url)); + FormAuthenticationFilter.onLoginSuccess(request, response); } catch (AuthenticationException e) { - if (!e.getMessage().startsWith("msg:")){ - throw new AuthenticationException("msg:登录失败,请联系管理员。", e); - } - throw e; + FormAuthenticationFilter.onLoginFailure(e, request, response); } + return null; } return "error/403"; } +// public static void main(String[] args) { +// System.out.println(UserUtils.getSsoToken("system")); +// } + }