diff --git a/modules/core/db/core.erm b/modules/core/db/core.erm
index 46bd6824..cab79408 100644
--- a/modules/core/db/core.erm
+++ b/modules/core/db/core.erm
@@ -11,8 +11,8 @@
0
1.0
- 3166
- 1170
+ 3413
+ 1172
128
128
@@ -12959,6 +12959,19 @@
+
+ false
+ true
+ idx_sys_msg_pushw_imp
+
+
+
+
+ 013bfa07b771054f43105d72d01324d96518fc38
+ false
+
+
+
@@ -13833,6 +13846,19 @@
+
+ false
+ true
+ idx_sys_msg_push_imp
+
+
+
+
+ 385ac7698fd3d6123c18f7cd819a83e80313f614
+ false
+
+
+
diff --git a/modules/core/db/oracle/core.sql b/modules/core/db/oracle/core.sql
index 4d3d8090..45497eb5 100644
--- a/modules/core/db/oracle/core.sql
+++ b/modules/core/db/oracle/core.sql
@@ -75,6 +75,7 @@ DROP INDEX idx_sys_msg_push_ps;
DROP INDEX idx_sys_msg_push_rs;
DROP INDEX idx_sys_msg_push_bk;
DROP INDEX idx_sys_msg_push_bt;
+DROP INDEX idx_sys_msg_push_imp;
DROP INDEX idx_sys_msg_pushw_type;
DROP INDEX idx_sys_msg_pushw_rc;
DROP INDEX idx_sys_msg_pushw_uc;
@@ -84,6 +85,7 @@ DROP INDEX idx_sys_msg_pushw_ps;
DROP INDEX idx_sys_msg_pushw_rs;
DROP INDEX idx_sys_msg_pushw_bk;
DROP INDEX idx_sys_msg_pushw_bt;
+DROP INDEX idx_sys_msg_pushw_imp;
DROP INDEX idx_sys_msg_tpl_key;
DROP INDEX idx_sys_msg_tpl_type;
DROP INDEX idx_sys_msg_tpl_status;
@@ -906,6 +908,7 @@ CREATE INDEX idx_sys_msg_push_ps ON js_sys_msg_push (push_status);
CREATE INDEX idx_sys_msg_push_rs ON js_sys_msg_push (read_status);
CREATE INDEX idx_sys_msg_push_bk ON js_sys_msg_push (biz_key);
CREATE INDEX idx_sys_msg_push_bt ON js_sys_msg_push (biz_type);
+CREATE INDEX idx_sys_msg_push_imp ON js_sys_msg_push (is_merge_push);
CREATE INDEX idx_sys_msg_pushw_type ON js_sys_msg_push_wait (msg_type);
CREATE INDEX idx_sys_msg_pushw_rc ON js_sys_msg_push_wait (receive_code);
CREATE INDEX idx_sys_msg_pushw_uc ON js_sys_msg_push_wait (receive_user_code);
@@ -915,6 +918,7 @@ CREATE INDEX idx_sys_msg_pushw_ps ON js_sys_msg_push_wait (push_status);
CREATE INDEX idx_sys_msg_pushw_rs ON js_sys_msg_push_wait (read_status);
CREATE INDEX idx_sys_msg_pushw_bk ON js_sys_msg_push_wait (biz_key);
CREATE INDEX idx_sys_msg_pushw_bt ON js_sys_msg_push_wait (biz_type);
+CREATE INDEX idx_sys_msg_pushw_imp ON js_sys_msg_push_wait (is_merge_push);
CREATE INDEX idx_sys_msg_tpl_key ON js_sys_msg_template (tpl_key);
CREATE INDEX idx_sys_msg_tpl_type ON js_sys_msg_template (tpl_type);
CREATE INDEX idx_sys_msg_tpl_status ON js_sys_msg_template (status);
diff --git a/modules/core/src/main/java/com/jeesite/common/shiro/realm/AuthorizingRealm.java b/modules/core/src/main/java/com/jeesite/common/shiro/realm/AuthorizingRealm.java
index 1c8150ce..53dcd3e3 100644
--- a/modules/core/src/main/java/com/jeesite/common/shiro/realm/AuthorizingRealm.java
+++ b/modules/core/src/main/java/com/jeesite/common/shiro/realm/AuthorizingRealm.java
@@ -1,75 +1,75 @@
-/**
- * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
- */
-package com.jeesite.common.shiro.realm;
-
-import java.util.Map;
-
-import org.apache.shiro.subject.PrincipalCollection;
-
-import com.jeesite.common.codec.EncodeUtils;
-import com.jeesite.common.lang.ObjectUtils;
-import com.jeesite.common.web.http.ServletUtils;
-import com.jeesite.modules.sys.entity.EmpUser;
-import com.jeesite.modules.sys.entity.User;
-import com.jeesite.modules.sys.service.EmpUserService;
-import com.jeesite.modules.sys.service.UserService;
-import com.jeesite.modules.sys.utils.LogUtils;
-import com.jeesite.modules.sys.utils.UserUtils;
-
-/**
- * 系统安全认证实现类
- * @author ThinkGem
- * @version 2017-03-22
- */
-public class AuthorizingRealm extends com.jeesite.common.shiro.realm.BaseAuthorizingRealm {
-
- private UserService userService;
- private EmpUserService empUserService;
-
- public AuthorizingRealm() {
- super();
- }
-
- @Override
- protected void casCreateEmpUser(User user, Map attributes) {
- EmpUser empUser = new EmpUser();
- empUser.setIsNewRecord(true);
- empUser.setMobile(user.getMobile());
- empUser.setEmail(user.getEmail());
- empUser.setPhone(user.getPhone());
- empUser.getEmployee().getCompany().setCompanyCode(EncodeUtils
- .decodeUrl(ObjectUtils.toString(attributes.get("companyCode"))));
- empUser.getEmployee().getOffice().setOfficeCode(EncodeUtils
- .decodeUrl(ObjectUtils.toString(attributes.get("officeCode"))));
- empUserService.save(empUser);
- }
-
- @Override
- public void onLoginSuccess(PrincipalCollection principals) {
- super.onLoginSuccess(principals);
-
- User user = UserUtils.getUser();
-
- // 更新登录IP、时间、会话ID等
- userService.updateUserLoginInfo(user);
-
- // 记录用户登录日志
- LogUtils.saveLog(ServletUtils.getRequest(), "系统登录");
- }
-
- @Override
- public void onSingleSignOut(User logoutUser) {
- // 记录用户退出日志
- LogUtils.saveLog(logoutUser, null, null, null, "系统退出");
- }
-
- public void setUserService(UserService userService) {
- this.userService = userService;
- }
-
- public void setEmpUserService(EmpUserService empUserService) {
- this.empUserService = empUserService;
- }
-
-}
+/**
+ * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
+ */
+package com.jeesite.common.shiro.realm;
+
+import java.util.Map;
+
+import org.apache.shiro.subject.PrincipalCollection;
+
+import com.jeesite.common.codec.EncodeUtils;
+import com.jeesite.common.lang.ObjectUtils;
+import com.jeesite.common.web.http.ServletUtils;
+import com.jeesite.modules.sys.entity.EmpUser;
+import com.jeesite.modules.sys.entity.User;
+import com.jeesite.modules.sys.service.EmpUserService;
+import com.jeesite.modules.sys.service.UserService;
+import com.jeesite.modules.sys.utils.LogUtils;
+import com.jeesite.modules.sys.utils.UserUtils;
+
+/**
+ * 系统安全认证实现类
+ * @author ThinkGem
+ * @version 2017-03-22
+ */
+public class AuthorizingRealm extends com.jeesite.common.shiro.realm.BaseAuthorizingRealm {
+
+ private UserService userService;
+ private EmpUserService empUserService;
+
+ public AuthorizingRealm() {
+ super();
+ }
+
+ @Override
+ protected void casCreateEmpUser(User user, Map attributes) {
+ EmpUser empUser = new EmpUser();
+ empUser.setIsNewRecord(true);
+ empUser.setMobile(user.getMobile());
+ empUser.setEmail(user.getEmail());
+ empUser.setPhone(user.getPhone());
+ empUser.getEmployee().getCompany().setCompanyCode(EncodeUtils
+ .decodeUrl(ObjectUtils.toString(attributes.get("companyCode"))));
+ empUser.getEmployee().getOffice().setOfficeCode(EncodeUtils
+ .decodeUrl(ObjectUtils.toString(attributes.get("officeCode"))));
+ empUserService.save(empUser);
+ }
+
+ @Override
+ public void onLoginSuccess(PrincipalCollection principals) {
+ super.onLoginSuccess(principals);
+
+ User user = UserUtils.getUser();
+
+ // 更新登录IP、时间、会话ID等
+ userService.updateUserLoginInfo(user);
+
+ // 记录用户登录日志
+ LogUtils.saveLog(ServletUtils.getRequest(), "系统登录");
+ }
+
+ @Override
+ public void onLogoutSuccess(User logoutUser) {
+ // 记录用户退出日志
+ LogUtils.saveLog(logoutUser, null, null, null, "系统退出");
+ }
+
+ public void setUserService(UserService userService) {
+ this.userService = userService;
+ }
+
+ public void setEmpUserService(EmpUserService empUserService) {
+ this.empUserService = empUserService;
+ }
+
+}
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 a3cd914b..1a243565 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
@@ -1,341 +1,341 @@
-/**
- * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
- */
-package com.jeesite.modules.sys.web;
-
-import java.util.Map;
-import java.util.Map.Entry;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.shiro.SecurityUtils;
-import org.apache.shiro.authz.AuthorizationInfo;
-import org.apache.shiro.authz.UnauthorizedException;
-import org.apache.shiro.authz.annotation.RequiresPermissions;
-import org.apache.shiro.session.Session;
-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 com.jeesite.common.config.Global;
-import com.jeesite.common.lang.ObjectUtils;
-import com.jeesite.common.lang.StringUtils;
-import com.jeesite.common.shiro.filter.FormAuthenticationFilter;
-import com.jeesite.common.shiro.realm.BaseAuthorizingRealm;
-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.User;
-import com.jeesite.modules.sys.service.UserService;
-import com.jeesite.modules.sys.utils.UserUtils;
-
-/**
- * 登录Controller
- * @author ThinkGem
- * @version 2017-03-25
- */
-@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;
- return REDIRECT + adminPath + "/login" + queryString;
- }
-
- LoginInfo loginInfo = UserUtils.getLoginInfo();
-
- // 如果已经登录,则跳转到管理首页
- if(loginInfo != null){
- String queryString = request.getQueryString();
- queryString = queryString == null ? "" : "?" + queryString;
- String indexUrl = adminPath + "/index" + queryString;
- if (ServletUtils.isAjaxRequest(request)){
- try {
- request.getRequestDispatcher(indexUrl).forward(request, response); // AJAX不支持Redirect改用Forward
- } catch (Exception ex) {
- logger.error(ex.getMessage(), ex);
- }
- return null;
- }
- return REDIRECT + indexUrl;
- }
-
- // 如果是登录操作,跳转到此,则认为是登录失败(支持GET登录时传递__login=true参数)
- if (WebUtils.isTrue(request, "__login")){
- return loginFailure(request, response, model);
- }
-
- // 如果已登录,再次访问主页,则退出原账号。
- if (!Global.TRUE.equals(Global.getConfig("shiro.isAllowRefreshIndex"))){
- CookieUtils.setCookie(response, "LOGINED", "false");
- }
-
- // 是否显示验证码
- model.addAttribute("isValidCodeLogin", ObjectUtils.toInteger(Global.getConfig("sys.login.failedNumAfterValidCode", "200")) == 0);
-
- // 获取登录参数
- Map paramMap = ServletUtils.getExtParams(request);
-
- // 如果登录设置了语言,则切换语言
- if (paramMap.get("lang") != null){
- Global.setLang((String)paramMap.get("lang"), request, response);
- }
-
- // 如果是Ajax请求,返回Json字符串。
- if (ServletUtils.isAjaxRequest((HttpServletRequest)request)){
- model.addAttribute("result", "login");
- model.addAttribute("message", text("未登录或登录超时。请重新登录,谢谢!"));
- return ServletUtils.renderObject(response, model);
- }
-
- // 返回指定用户类型的登录页视图
- String userType = (String)paramMap.get("userType");
- if (StringUtils.isNotBlank(userType)){
- 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;
- String indexUrl = adminPath + "/index" + queryString;
- if (ServletUtils.isAjaxRequest(request)){
- try {
- request.getRequestDispatcher(indexUrl).forward(request, response); // AJAX不支持Redirect改用Forward
- } catch (Exception ex) {
- logger.error(ex.getMessage(), ex);
- }
- return null;
- }
- return REDIRECT + indexUrl;
- }
-
- String username = WebUtils.getCleanParam(request, FormAuthenticationFilter.DEFAULT_USERNAME_PARAM);
- boolean rememberMe = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM);
- boolean rememberUserCode = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_USERCODE_PARAM);
- String params = WebUtils.getCleanParam(request, FormAuthenticationFilter.DEFAULT_PARAMS_PARAM);
- String exception = (String)request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
- String message = (String)request.getAttribute(FormAuthenticationFilter.DEFAULT_MESSAGE_PARAM);
-
- model.addAttribute(FormAuthenticationFilter.DEFAULT_USERNAME_PARAM, username);
- model.addAttribute(FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM, rememberMe);
- model.addAttribute(FormAuthenticationFilter.DEFAULT_REMEMBER_USERCODE_PARAM, rememberUserCode);
- model.addAttribute(FormAuthenticationFilter.DEFAULT_PARAMS_PARAM, params);
- Map paramMap = ServletUtils.getExtParams(request);
- for (Entry entry : paramMap.entrySet()){
- model.addAttribute(FormAuthenticationFilter.DEFAULT_PARAM_PREFIX_PARAM + entry.getKey(), entry.getValue());
- }
- model.addAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME, exception);
-
- // 如果登录设置了语言,则切换语言
- if (paramMap.get("lang") != null){
- Global.setLang((String)paramMap.get("lang"), request, response);
- }
-
- model.addAttribute(FormAuthenticationFilter.DEFAULT_MESSAGE_PARAM, text(message));
-
- // 非授权异常,登录失败,验证码加1。
- if (!UnauthorizedException.class.getName().equals(exception)){
-// // 如果使用了集团用户模式,则获取集团Code
-// String corpCode = null;
-// if (Global.isUseCorpModel()){
-// corpCode = (String)paramMap.get("corpCode");
-// if (StringUtils.isBlank(corpCode)){
-// throw new AuthenticationException("msg:请选择您要登录的集团公司.");
-// }
-// }
- model.addAttribute("isValidCodeLogin", BaseAuthorizingRealm.isValidCodeLogin(username, /*corpCode, */(String)paramMap.get("deviceType"), "failed"));
- }
-
- // 登录操作如果是Ajax操作,直接返回登录信息字符串。
- if (ServletUtils.isAjaxRequest(request)){
- model.addAttribute("result", Global.FALSE);
- return ServletUtils.renderObject(response, model);
- }
-
- // 返回指定用户类型的登录页视图
- String userType = (String)paramMap.get("userType");
- if (StringUtils.isNotBlank(userType)){
- 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;
- return REDIRECT + adminPath + "/index" + queryString;
- }
-
- // 验证下用户权限,以便调用doGetAuthorizationInfo方法,保存单点登录登出句柄
- if (!SecurityUtils.getSubject().isPermitted("user")){
- return REDIRECT + adminPath + "/login";
- }
-
- //获取登录用户信息
- LoginInfo loginInfo = UserUtils.getLoginInfo();
-
- // 未加载shiro模块时会为空,直接访问则提示操作权限不足。
- if(loginInfo == null){
- UserUtils.getSubject().logout();
- return REDIRECT + adminPath + "/login";
- }
-
- // 当前用户对象信息
- User user = UserUtils.get(loginInfo.getId());
- if (user == null){
- UserUtils.getSubject().logout();
- return REDIRECT + adminPath + "/login";
- }
- model.addAttribute("user", user); // 设置当前用户信息
-
- // 登录成功后,验证码计算器清零
- BaseAuthorizingRealm.isValidCodeLogin(loginInfo.getId(), /*loginInfo.getParam("corpCode"), */loginInfo.getParam("deviceType"), "success");
-
- //获取当前会话对象
- Session session = UserUtils.getSession();
-
- // 设置共享SessionId的Cookie值,睿思BI使用。
- String cookieName = Global.getProperty("session.shareSessionIdCookieName");
- CookieUtils.setCookie((HttpServletResponse)response, cookieName, (String)session.getId());
-
- // 如果是登录操作,则设置登录信息(移动端用)
- model.addAttribute("result", Global.TRUE);
- if (request.getParameter("username") != null && request.getParameter("password") != null){
- // 如果登录设置了语言,则切换语言
- if (loginInfo.getParam("lang") != null){
- Global.setLang(loginInfo.getParam("lang"), request, response);
- }
- model.addAttribute("message", text("登录成功!"));
- }else{
- model.addAttribute("message", text("获取信息成功!"));
- }
- model.addAttribute("sessionid", (String)session.getId());
- // 授权信息获取
- AuthorizationInfo authInfo = null;
- // 获取当前用户权限字符串
- if (WebUtils.isTrue(request, "permi")){
- if (authInfo == null){
- authInfo = (AuthorizationInfo)UserUtils.getCache(UserUtils.CACHE_AUTH_INFO);
- }
- model.addAttribute("permi", authInfo.getStringPermissions());
- }
-
- // 登录操作如果是Ajax操作,直接返回登录信息字符串。
- if (ServletUtils.isAjaxRequest(request)){
- return ServletUtils.renderObject(response, model);
- }
-
- // 是否允许刷新主页,如果已登录,再次访问主页,则退出原账号。
- if (!ObjectUtils.toBoolean(Global.getConfig("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 = UserService.passwordModifyValid(user, model);
- if (passwordModifyUrl != null){
- try {
- request.getRequestDispatcher(passwordModifyUrl).forward(request, response);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return null;
- }
-
- // 返回指定用户类型的首页视图
- String view = UserUtils.getUserTypeValue(user.getUserType(), "indexView");
- if(StringUtils.isNotBlank(view)){
- return view;
- }
-
- // 返回主页面视图
- return "modules/sys/sysIndex";
- }
-
- /**
- * 切换系统菜单(仅超级管理员有权限)
- */
- @RequiresPermissions("user")
- @RequestMapping(value = "switch/{sysCode}")
- public String switchSys(@PathVariable String sysCode) {
- LoginInfo principal = UserUtils.getLoginInfo();
- User user = UserUtils.get(principal.getId());
- if (user.isSuperAdmin() && StringUtils.isNotBlank(sysCode)){
- if (!StringUtils.equals(principal.getParam("sysCode"), sysCode)){
- principal.setParam("sysCode", sysCode);
- UserUtils.removeCache(UserUtils.CACHE_AUTH_INFO);
- UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
- }
- }
- 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/sysSwitchSkin";
- }
-
- /**
- * 个人桌面页面
- */
- @RequiresPermissions("user")
- @RequestMapping(value = "desktop")
- public String desktop(HttpServletRequest request, HttpServletResponse response, Model model) {
- return "modules/sys/sysDesktop";
- }
-
-}
+/**
+ * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
+ */
+package com.jeesite.modules.sys.web;
+
+import java.util.Map;
+import java.util.Map.Entry;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.UnauthorizedException;
+import org.apache.shiro.authz.annotation.RequiresPermissions;
+import org.apache.shiro.session.Session;
+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 com.jeesite.common.config.Global;
+import com.jeesite.common.lang.ObjectUtils;
+import com.jeesite.common.lang.StringUtils;
+import com.jeesite.common.shiro.filter.FormAuthenticationFilter;
+import com.jeesite.common.shiro.realm.BaseAuthorizingRealm;
+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.User;
+import com.jeesite.modules.sys.service.UserService;
+import com.jeesite.modules.sys.utils.UserUtils;
+
+/**
+ * 登录Controller
+ * @author ThinkGem
+ * @version 2017-03-25
+ */
+@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;
+// return REDIRECT + adminPath + "/login" + queryString;
+// }
+
+ LoginInfo loginInfo = UserUtils.getLoginInfo();
+
+ // 如果已经登录,则跳转到管理首页
+ if(loginInfo != null){
+ String queryString = request.getQueryString();
+ queryString = queryString == null ? "" : "?" + queryString;
+ String indexUrl = adminPath + "/index" + queryString;
+ if (ServletUtils.isAjaxRequest(request)){
+ try {
+ request.getRequestDispatcher(indexUrl).forward(request, response); // AJAX不支持Redirect改用Forward
+ } catch (Exception ex) {
+ logger.error(ex.getMessage(), ex);
+ }
+ return null;
+ }
+ return REDIRECT + indexUrl;
+ }
+
+ // 如果是登录操作,跳转到此,则认为是登录失败(支持GET登录时传递__login=true参数)
+ if (WebUtils.isTrue(request, "__login")){
+ return loginFailure(request, response, model);
+ }
+
+ // 如果已登录,再次访问主页,则退出原账号。
+ if (!Global.TRUE.equals(Global.getConfig("shiro.isAllowRefreshIndex"))){
+ CookieUtils.setCookie(response, "LOGINED", "false");
+ }
+
+ // 是否显示验证码
+ model.addAttribute("isValidCodeLogin", ObjectUtils.toInteger(Global.getConfig("sys.login.failedNumAfterValidCode", "200")) == 0);
+
+ // 获取登录参数
+ Map paramMap = ServletUtils.getExtParams(request);
+
+ // 如果登录设置了语言,则切换语言
+ if (paramMap.get("lang") != null){
+ Global.setLang((String)paramMap.get("lang"), request, response);
+ }
+
+ // 如果是Ajax请求,返回Json字符串。
+ if (ServletUtils.isAjaxRequest((HttpServletRequest)request)){
+ model.addAttribute("result", "login");
+ model.addAttribute("message", text("未登录或登录超时。请重新登录,谢谢!"));
+ return ServletUtils.renderObject(response, model);
+ }
+
+ // 返回指定用户类型的登录页视图
+ String userType = (String)paramMap.get("userType");
+ if (StringUtils.isNotBlank(userType)){
+ 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;
+ String indexUrl = adminPath + "/index" + queryString;
+ if (ServletUtils.isAjaxRequest(request)){
+ try {
+ request.getRequestDispatcher(indexUrl).forward(request, response); // AJAX不支持Redirect改用Forward
+ } catch (Exception ex) {
+ logger.error(ex.getMessage(), ex);
+ }
+ return null;
+ }
+ return REDIRECT + indexUrl;
+ }
+
+ String username = WebUtils.getCleanParam(request, FormAuthenticationFilter.DEFAULT_USERNAME_PARAM);
+ boolean rememberMe = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM);
+ boolean rememberUserCode = WebUtils.isTrue(request, FormAuthenticationFilter.DEFAULT_REMEMBER_USERCODE_PARAM);
+ String params = WebUtils.getCleanParam(request, FormAuthenticationFilter.DEFAULT_PARAMS_PARAM);
+ String exception = (String)request.getAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME);
+ String message = (String)request.getAttribute(FormAuthenticationFilter.DEFAULT_MESSAGE_PARAM);
+
+ model.addAttribute(FormAuthenticationFilter.DEFAULT_USERNAME_PARAM, username);
+ model.addAttribute(FormAuthenticationFilter.DEFAULT_REMEMBER_ME_PARAM, rememberMe);
+ model.addAttribute(FormAuthenticationFilter.DEFAULT_REMEMBER_USERCODE_PARAM, rememberUserCode);
+ model.addAttribute(FormAuthenticationFilter.DEFAULT_PARAMS_PARAM, params);
+ Map paramMap = ServletUtils.getExtParams(request);
+ for (Entry entry : paramMap.entrySet()){
+ model.addAttribute(FormAuthenticationFilter.DEFAULT_PARAM_PREFIX_PARAM + entry.getKey(), entry.getValue());
+ }
+ model.addAttribute(FormAuthenticationFilter.DEFAULT_ERROR_KEY_ATTRIBUTE_NAME, exception);
+
+ // 如果登录设置了语言,则切换语言
+ if (paramMap.get("lang") != null){
+ Global.setLang((String)paramMap.get("lang"), request, response);
+ }
+
+ model.addAttribute(FormAuthenticationFilter.DEFAULT_MESSAGE_PARAM, text(message));
+
+ // 非授权异常,登录失败,验证码加1。
+ if (!UnauthorizedException.class.getName().equals(exception)){
+// // 如果使用了集团用户模式,则获取集团Code
+// String corpCode = null;
+// if (Global.isUseCorpModel()){
+// corpCode = (String)paramMap.get("corpCode");
+// if (StringUtils.isBlank(corpCode)){
+// throw new AuthenticationException("msg:请选择您要登录的集团公司.");
+// }
+// }
+ model.addAttribute("isValidCodeLogin", BaseAuthorizingRealm.isValidCodeLogin(username, /*corpCode, */(String)paramMap.get("deviceType"), "failed"));
+ }
+
+ // 登录操作如果是Ajax操作,直接返回登录信息字符串。
+ if (ServletUtils.isAjaxRequest(request)){
+ model.addAttribute("result", Global.FALSE);
+ return ServletUtils.renderObject(response, model);
+ }
+
+ // 返回指定用户类型的登录页视图
+ String userType = (String)paramMap.get("userType");
+ if (StringUtils.isNotBlank(userType)){
+ 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;
+// return REDIRECT + adminPath + "/index" + queryString;
+// }
+
+ // 验证下用户权限,以便调用doGetAuthorizationInfo方法,保存单点登录登出句柄
+ if (!SecurityUtils.getSubject().isPermitted("user")){
+ return REDIRECT + adminPath + "/login";
+ }
+
+ //获取登录用户信息
+ LoginInfo loginInfo = UserUtils.getLoginInfo();
+
+ // 未加载shiro模块时会为空,直接访问则提示操作权限不足。
+ if(loginInfo == null){
+ UserUtils.getSubject().logout();
+ return REDIRECT + adminPath + "/login";
+ }
+
+ // 当前用户对象信息
+ User user = UserUtils.get(loginInfo.getId());
+ if (user == null){
+ UserUtils.getSubject().logout();
+ return REDIRECT + adminPath + "/login";
+ }
+ model.addAttribute("user", user); // 设置当前用户信息
+
+ // 登录成功后,验证码计算器清零
+ BaseAuthorizingRealm.isValidCodeLogin(loginInfo.getId(), /*loginInfo.getParam("corpCode"), */loginInfo.getParam("deviceType"), "success");
+
+ //获取当前会话对象
+ Session session = UserUtils.getSession();
+
+ // 设置共享SessionId的Cookie值,睿思BI使用。
+ String cookieName = Global.getProperty("session.shareSessionIdCookieName");
+ CookieUtils.setCookie((HttpServletResponse)response, cookieName, (String)session.getId());
+
+ // 如果是登录操作,则设置登录信息(移动端用)
+ model.addAttribute("result", Global.TRUE);
+ if (request.getParameter("username") != null && request.getParameter("password") != null){
+ // 如果登录设置了语言,则切换语言
+ if (loginInfo.getParam("lang") != null){
+ Global.setLang(loginInfo.getParam("lang"), request, response);
+ }
+ model.addAttribute("message", text("登录成功!"));
+ }else{
+ model.addAttribute("message", text("获取信息成功!"));
+ }
+ model.addAttribute("sessionid", (String)session.getId());
+ // 授权信息获取
+ AuthorizationInfo authInfo = null;
+ // 获取当前用户权限字符串
+ if (WebUtils.isTrue(request, "permi")){
+ if (authInfo == null){
+ authInfo = (AuthorizationInfo)UserUtils.getCache(UserUtils.CACHE_AUTH_INFO);
+ }
+ model.addAttribute("permi", authInfo.getStringPermissions());
+ }
+
+ // 登录操作如果是Ajax操作,直接返回登录信息字符串。
+ if (ServletUtils.isAjaxRequest(request)){
+ return ServletUtils.renderObject(response, model);
+ }
+
+ // 是否允许刷新主页,如果已登录,再次访问主页,则退出原账号。
+ if (!ObjectUtils.toBoolean(Global.getConfig("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 = UserService.passwordModifyValid(user, model);
+ if (passwordModifyUrl != null){
+ try {
+ request.getRequestDispatcher(passwordModifyUrl).forward(request, response);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
+ // 返回指定用户类型的首页视图
+ String view = UserUtils.getUserTypeValue(user.getUserType(), "indexView");
+ if(StringUtils.isNotBlank(view)){
+ return view;
+ }
+
+ // 返回主页面视图
+ return "modules/sys/sysIndex";
+ }
+
+ /**
+ * 切换系统菜单(仅超级管理员有权限)
+ */
+ @RequiresPermissions("user")
+ @RequestMapping(value = "switch/{sysCode}")
+ public String switchSys(@PathVariable String sysCode) {
+ LoginInfo principal = UserUtils.getLoginInfo();
+ User user = UserUtils.get(principal.getId());
+ if (user.isSuperAdmin() && StringUtils.isNotBlank(sysCode)){
+ if (!StringUtils.equals(principal.getParam("sysCode"), sysCode)){
+ principal.setParam("sysCode", sysCode);
+ UserUtils.removeCache(UserUtils.CACHE_AUTH_INFO);
+ UserUtils.removeCache(UserUtils.CACHE_MENU_LIST);
+ }
+ }
+ 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/sysSwitchSkin";
+ }
+
+ /**
+ * 个人桌面页面
+ */
+ @RequiresPermissions("user")
+ @RequestMapping(value = "desktop")
+ public String desktop(HttpServletRequest request, HttpServletResponse response, Model model) {
+ return "modules/sys/sysDesktop";
+ }
+
+}
diff --git a/modules/core/src/main/java/com/jeesite/modules/sys/web/OnlineController.java b/modules/core/src/main/java/com/jeesite/modules/sys/web/OnlineController.java
index a77ed009..0450aef0 100644
--- a/modules/core/src/main/java/com/jeesite/modules/sys/web/OnlineController.java
+++ b/modules/core/src/main/java/com/jeesite/modules/sys/web/OnlineController.java
@@ -1,151 +1,151 @@
-/**
- * Copyright (c) 2013-Now http://jeesite.com All rights reserved.
- */
-package com.jeesite.modules.sys.web;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.shiro.authz.annotation.RequiresPermissions;
-import org.apache.shiro.session.Session;
-import org.apache.shiro.subject.PrincipalCollection;
-import org.apache.shiro.subject.support.DefaultSubjectContext;
-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.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.ResponseBody;
-
-import com.beust.jcommander.internal.Lists;
-import com.beust.jcommander.internal.Maps;
-import com.jeesite.common.config.Global;
-import com.jeesite.common.lang.DateUtils;
-import com.jeesite.common.lang.ObjectUtils;
-import com.jeesite.common.lang.StringUtils;
-import com.jeesite.common.lang.TimeUtils;
-import com.jeesite.common.shiro.realm.LoginInfo;
-import com.jeesite.common.shiro.session.SessionDAO;
-import com.jeesite.common.web.BaseController;
-import com.jeesite.modules.sys.utils.UserUtils;
-
-/**
- * 在线用户Controller
- * @author ThinkGem
- * @version 2016-8-31
- */
-@Controller
-@RequestMapping(value = "${adminPath}/sys/online")
-public class OnlineController extends BaseController{
-
- @Autowired
- private SessionDAO sessionDAO;
-
- /**
- * 在线用户数
- * @param request
- * @param response
- * @author ThinkGem
- */
- @RequestMapping(value = "count")
- @ResponseBody
- public Integer count(HttpServletRequest request, HttpServletResponse response) {
- return sessionDAO.getActiveSessions(true, true).size();
- }
-
- /**
- * 在线用户列表
- * @param request
- * @param response
- * @param model
- */
- @RequiresPermissions("sys:online:view")
- @RequestMapping(value = "list")
- public String list(Model model) {
- return "modules/sys/onlineList";
- }
-
- /**
- * 在线用户列表数据
- * @param request
- * @param response
- * @author ThinkGem
- */
- @RequiresPermissions("sys:online:view")
- @RequestMapping(value = "listData")
- @ResponseBody
- public List