ソースを参照

增加强制退出会话

shuzheng 9 年 前
コミット
2f5b56f7bf

+ 18 - 1
zheng-common/src/main/java/com/zheng/common/util/RedisUtil.java

@@ -133,7 +133,7 @@ public class RedisUtil {
 	}
 
 	/**
-	 * 设置 过期时间
+	 * 设置 String 过期时间
 	 * @param key
 	 * @param value
 	 * @param seconds 以秒为单位
@@ -149,6 +149,23 @@ public class RedisUtil {
 		}
 	}
 
+	/**
+	 * 设置 byte[] 过期时间
+	 * @param key
+	 * @param value
+	 * @param seconds 以秒为单位
+	 */
+	public synchronized static void set(byte[] key, byte[] value, int seconds) {
+		try {
+			Jedis jedis = getJedis();
+			jedis.set(key, value);
+			jedis.expire(key, seconds);
+			jedis.close();
+		} catch (Exception e) {
+			_log.error("Set key error : " + e);
+		}
+	}
+
 	/**
 	 * 获取String值
 	 * @param key

+ 8 - 21
zheng-upms/zheng-upms-server/src/main/java/com/zheng/upms/server/controller/manage/UpmsSessionController.java

@@ -1,37 +1,24 @@
 package com.zheng.upms.server.controller.manage;
 
-import com.baidu.unbiz.fluentvalidator.ComplexResult;
-import com.baidu.unbiz.fluentvalidator.FluentValidator;
-import com.baidu.unbiz.fluentvalidator.ResultCollectors;
 import com.zheng.common.base.BaseController;
-import com.zheng.common.validator.LengthValidator;
 import com.zheng.upms.common.constant.UpmsResult;
 import com.zheng.upms.common.constant.UpmsResultConstant;
-import com.zheng.upms.dao.model.UpmsSystem;
-import com.zheng.upms.dao.model.UpmsSystemExample;
-import com.zheng.upms.rpc.api.UpmsSystemService;
 import com.zheng.upms.server.shiro.UpmsSessionDao;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
-import org.apache.commons.lang.StringUtils;
 import org.apache.shiro.authz.annotation.RequiresPermissions;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
-import org.springframework.ui.ModelMap;
 import org.springframework.web.bind.annotation.*;
 
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
 /**
  * 会话管理controller
  * Created by shuzheng on 2017/2/28.
  */
 @Controller
-@Api(value = "系统管理", description = "系统管理")
+@Api(value = "会话管理", description = "会话管理")
 @RequestMapping("/manage/session")
 public class UpmsSessionController extends BaseController {
 
@@ -40,14 +27,14 @@ public class UpmsSessionController extends BaseController {
 	@Autowired
 	private UpmsSessionDao sessionDAO;
 
-	@ApiOperation(value = "系统首页")
+	@ApiOperation(value = "会话首页")
 	@RequiresPermissions("upms:session:read")
 	@RequestMapping(value = "/index", method = RequestMethod.GET)
 	public String index() {
 		return "/manage/session/index";
 	}
 
-	@ApiOperation(value = "系统列表")
+	@ApiOperation(value = "会话列表")
 	@RequiresPermissions("upms:session:read")
 	@RequestMapping(value = "/list", method = RequestMethod.GET)
 	@ResponseBody
@@ -57,12 +44,12 @@ public class UpmsSessionController extends BaseController {
 		return sessionDAO.getActiveSessions(offset, limit);
 	}
 
-	@ApiOperation(value = "删除系统")
-	@RequiresPermissions("upms:session:delete")
-	@RequestMapping(value = "/delete/{ids}",method = RequestMethod.GET)
+	@ApiOperation(value = "强制退出")
+	@RequiresPermissions("upms:session:forceout")
+	@RequestMapping(value = "/forceout/{ids}",method = RequestMethod.GET)
 	@ResponseBody
-	public Object delete(@PathVariable("ids") String ids) {
-		int count = sessionDAO.deleteByPrimaryKeys(ids);
+	public Object forceout(@PathVariable("ids") String ids) {
+		int count = sessionDAO.forceout(ids);
 		return new UpmsResult(UpmsResultConstant.SUCCESS, count);
 	}
 

+ 20 - 23
zheng-upms/zheng-upms-server/src/main/java/com/zheng/upms/server/shiro/UpmsSessionDao.java

@@ -35,7 +35,7 @@ public class UpmsSessionDao extends EnterpriseCacheSessionDAO {
     @Override
     protected Serializable doCreate(Session session) {
         Serializable sessionId = super.doCreate(session);
-        RedisUtil.set(sessionToByte(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + sessionId), sessionToByte(session));
+        RedisUtil.set((ZHENG_UPMS_SHIRO_SESSION_ID + "_" + sessionId).getBytes(), sessionToByte(session), (int) session.getTimeout() / 1000);
         _log.debug("[UpmsSessionDao]创建session: sessionId={}", session.getId());
         // 维护会话id列表,提供会话分页管理
         Jedis jedis = RedisUtil.getJedis();
@@ -49,7 +49,7 @@ public class UpmsSessionDao extends EnterpriseCacheSessionDAO {
         // 先从缓存中获取session,如果没有再去redis中获取
         Session session = super.doReadSession(sessionId);
         if(session == null){
-            byte[] bytes = RedisUtil.get(sessionId.toString().getBytes());
+            byte[] bytes = RedisUtil.get((ZHENG_UPMS_SHIRO_SESSION_ID + "_" + sessionId).getBytes());
             if(null != bytes && bytes.length > 0){
                 session = (Session) byteToSession(bytes);
                 _log.debug("[UpmsSessionDao]redis中获取session: sessionId={}", session.getId());
@@ -62,8 +62,8 @@ public class UpmsSessionDao extends EnterpriseCacheSessionDAO {
     protected void doUpdate(Session session) {
         // 更新session的最后一次访问时间
         super.doUpdate(session);
-        RedisUtil.set(session.getId().toString().getBytes(), sessionToByte(session));
-        _log.debug("[UpmsSessionDao]redis中更新session: sessionId={}", session.getId());
+        RedisUtil.set((ZHENG_UPMS_SHIRO_SESSION_ID + "_" + session.getId()).getBytes(), sessionToByte(session), (int) session.getTimeout() / 1000);
+        _log.debug("[UpmsSessionDao]redis中更新session: sessionId={}, seconds={}", session.getId(), (int) session.getTimeout() / 1000);
     }
 
     @Override
@@ -88,7 +88,7 @@ public class UpmsSessionDao extends EnterpriseCacheSessionDAO {
 
         // 删除session
         super.doDelete(session);
-        RedisUtil.remove(sessionToByte(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + serverSessionId));
+        RedisUtil.remove((ZHENG_UPMS_SHIRO_SESSION_ID + "_" + serverSessionId).getBytes());
         _log.debug("[UpmsSessionDao]redis中删除session: sessionId={}", session.getId());
 
         // 维护会话id列表,提供会话分页管理
@@ -105,7 +105,6 @@ public class UpmsSessionDao extends EnterpriseCacheSessionDAO {
      */
     public Map getActiveSessions(int offset, int limit) {
         Map sessions = new HashMap();
-
         Jedis jedis = RedisUtil.getJedis();
         // 获取在线会话总数
         long total = jedis.llen(ZHENG_UPMS_SHIRO_SESSION_IDS);
@@ -113,7 +112,7 @@ public class UpmsSessionDao extends EnterpriseCacheSessionDAO {
         List<String> ids = jedis.lrange(ZHENG_UPMS_SHIRO_SESSION_IDS, offset, (offset + limit - 1));
         List<Session> rows = new ArrayList<>();
         for (String id : ids) {
-            byte[] bytes = RedisUtil.get(id.getBytes());
+            byte[] bytes = RedisUtil.get((ZHENG_UPMS_SHIRO_SESSION_ID + "_" + id).getBytes());
             if(null != bytes && bytes.length > 0){
                 Session session = (Session) byteToSession(bytes);
                 rows.add(session);
@@ -126,13 +125,19 @@ public class UpmsSessionDao extends EnterpriseCacheSessionDAO {
     }
 
     /**
-     * 删除会话
+     * 强制退出
      * @param ids
      * @return
      */
-    public int deleteByPrimaryKeys(String ids) {
+    public int forceout(String ids) {
         String[] sessionIds = ids.split(",");
         for (String serverSessionId : sessionIds) {
+//            byte[] bytes = RedisUtil.get((ZHENG_UPMS_SHIRO_SESSION_ID + "_" + serverSessionId).getBytes());
+//            if(null != bytes && bytes.length > 0) {
+//                Session session = (Session) byteToSession(bytes);
+//                doDelete(session);
+//            }
+
             // 清空所有注册的局部会话和token
             // 当前全局会话token
             String token = RedisUtil.get(ZHENG_UPMS_SERVER_SESSION_ID + "_" + serverSessionId);
@@ -150,22 +155,14 @@ public class UpmsSessionDao extends EnterpriseCacheSessionDAO {
             _log.debug("当前token={},对应的注册系统个数:{}个", token, jedis.scard(ZHENG_UPMS_CLIENT_SESSION_IDS + "_" + token));
             jedis.close();
 
-            byte[] bytes = RedisUtil.get(serverSessionId.getBytes());
+            // 会话增加强制退出属性标识,当此会话访问系统时,判断有该标识,则退出登录
+            byte[] bytes = RedisUtil.get((ZHENG_UPMS_SHIRO_SESSION_ID + "_" + serverSessionId).getBytes());
             if(null != bytes && bytes.length > 0){
                 UpmsSession session = (UpmsSession) byteToSession(bytes);
-//                session.setStatus(UpmsSession.OnlineStatus.force_logout);
-//                super.doUpdate(session);
-//                RedisUtil.set(session.getId().toString().getBytes(), sessionToByte(session));
-                // 删除session
-                super.doDelete(session);
-                RedisUtil.remove(sessionToByte(ZHENG_UPMS_SHIRO_SESSION_ID + "_" + serverSessionId));
-                _log.debug("[UpmsSessionDao]redis中删除session: sessionId={}", session.getId());
-
-                // 维护会话id列表,提供会话分页管理
-                jedis = RedisUtil.getJedis();
-                jedis.lrem(ZHENG_UPMS_SHIRO_SESSION_IDS, 1, serverSessionId);
-                jedis.close();
-                // TODO logout
+                session.setStatus(UpmsSession.OnlineStatus.force_logout);
+                session.setAttribute("FORCE_LOGOUT", "FORCE_LOGOUT");
+                super.doUpdate(session);
+                RedisUtil.set((ZHENG_UPMS_SHIRO_SESSION_ID + "_" + session.getId()).getBytes(), sessionToByte(session), (int) session.getTimeout() / 1000);
             }
         }
         return sessionIds.length;

+ 33 - 0
zheng-upms/zheng-upms-server/src/main/java/com/zheng/upms/server/shiro/UpmsSessionForceLogoutFilter.java

@@ -0,0 +1,33 @@
+package com.zheng.upms.server.shiro;
+
+import org.apache.shiro.session.Session;
+import org.apache.shiro.web.filter.AccessControlFilter;
+import org.apache.shiro.web.util.WebUtils;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+/**
+ * 强制退出会话过滤器
+ * Created by shuzheng on 2017/3/1.
+ */
+public class UpmsSessionForceLogoutFilter extends AccessControlFilter {
+
+    @Override
+    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
+        Session session = getSubject(request, response).getSession(false);
+        if(session == null) {
+            return true;
+        }
+        return session.getAttribute("FORCE_LOGOUT") == null;
+    }
+
+    @Override
+    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
+        getSubject(request, response).logout();
+        String loginUrl = getLoginUrl() + (getLoginUrl().contains("?") ? "&" : "?") + "forceLogout=1";
+        WebUtils.issueRedirect(request, response, loginUrl);
+        return false;
+    }
+
+}

+ 4 - 1
zheng-upms/zheng-upms-server/src/main/resources/applicationContext-shiro.xml

@@ -22,12 +22,15 @@
                 /swagger-ui.html = user
                 /druid/** = user
                 /manage/index = user
-                /manage/** = authc
+                /manage/** = upmsSessionForceLogout,authc
                 /** = anon
             </value>
         </property>
     </bean>
 
+    <!-- 强制退出会话过滤器 -->
+    <bean id="upmsSessionForceLogout" class="com.zheng.upms.server.shiro.UpmsSessionForceLogoutFilter"/>
+
     <!-- 安全管理器 -->
     <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
         <property name="realms">

+ 8 - 8
zheng-upms/zheng-upms-server/src/main/webapp/WEB-INF/jsp/manage/session/index.jsp

@@ -18,7 +18,7 @@
 <body>
 <div id="main">
 	<div id="toolbar">
-		<shiro:hasPermission name="upms:session:delete"><a class="waves-effect waves-button" href="javascript:;" onclick="deleteAction()"><i class="zmdi zmdi-comment-alt-text"></i> 删除会话</a></shiro:hasPermission>
+		<shiro:hasPermission name="upms:session:forceout"><a class="waves-effect waves-button" href="javascript:;" onclick="forceoutAction()"><i class="zmdi zmdi-run"></i> 强制退出</a></shiro:hasPermission>
 	</div>
 	<table id="table"></table>
 </div>
@@ -60,9 +60,9 @@ $(function() {
 		]
 	});
 });
-// 删除
-var deleteDialog;
-function deleteAction() {
+// 强制退出
+var forceoutDialog;
+function forceoutAction() {
 	var rows = $table.bootstrapTable('getSelections');
 	if (rows.length == 0) {
 		$.confirm({
@@ -78,11 +78,11 @@ function deleteAction() {
 			}
 		});
 	} else {
-		deleteDialog = $.confirm({
+		forceoutDialog = $.confirm({
 			type: 'red',
 			animationSpeed: 300,
 			title: false,
-			content: '确认删除该会话吗?',
+			content: '确认强制退出该会话吗?',
 			buttons: {
 				confirm: {
 					text: '确认',
@@ -94,7 +94,7 @@ function deleteAction() {
 						}
 						$.ajax({
 							type: 'get',
-							url: '${basePath}/manage/session/delete/' + ids.join(","),
+							url: '${basePath}/manage/session/forceout/' + ids.join(","),
 							success: function(result) {
 								if (result.code != 1) {
 									if (result.data instanceof Array) {
@@ -129,7 +129,7 @@ function deleteAction() {
 										});
 									}
 								} else {
-									deleteDialog.close();
+									forceoutDialog.close();
 									$table.bootstrapTable('refresh');
 								}
 							},