Browse Source

v2.9.0 & loginSession

MaxKey 3 years ago
parent
commit
f80582fbb3

+ 1 - 0
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/AbstractAuthenticationProvider.java

@@ -331,6 +331,7 @@ public abstract class AbstractAuthenticationProvider {
             _logger.debug("login user  " + username + " not in this System ." + message);
             UserInfo loginUser = new UserInfo(username);
             loginUser.setId(loginUser.generateId());
+            loginUser.setUsername(username);
             loginUser.setDisplayName("not exist");
             loginUser.setLoginCount(0);
             authenticationRealm.insertLoginHistory(loginUser, ConstantsLoginType.LOCAL, "",

+ 1 - 1
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/RealmAuthenticationProvider.java

@@ -94,7 +94,7 @@ public class RealmAuthenticationProvider extends AbstractAuthenticationProvider
 
         userInfo =  loadUserInfo(loginCredential.getUsername(),loginCredential.getPassword());
 
-        userinfoValid(userInfo, loginCredential.getPassword());
+        userinfoValid(userInfo, loginCredential.getUsername());
 
         tftcaptchaValid(loginCredential.getOtpCaptcha(),loginCredential.getAuthType(),userInfo);
 

+ 5 - 4
maxkey-authentications/maxkey-authentication-core/src/main/java/org/maxkey/authn/realm/AbstractAuthenticationRealm.java

@@ -139,15 +139,16 @@ public abstract class AbstractAuthenticationRealm {
     public boolean insertLoginHistory(UserInfo userInfo, String type, String provider, String code, String message) {
         String sessionId = WebContext.genId();
         OnlineTicket onlineTicket = null ;
+        int sessionStatus = 7;
         Authentication authentication = WebContext.getAuthentication();
-        if(authentication.getPrincipal() instanceof SigninPrincipal) {
+        if(authentication !=null && authentication.getPrincipal() instanceof SigninPrincipal) {
+            sessionStatus = 1;
             SigninPrincipal signinPrincipal = (SigninPrincipal)authentication.getPrincipal();
             onlineTicket = signinPrincipal.getOnlineTicket();
             sessionId = onlineTicket.getTicketId().substring(3);
+            WebContext.setAttribute(WebConstants.CURRENT_USER_SESSION_ID, sessionId);
         }
         
-        WebContext.setAttribute(WebConstants.CURRENT_USER_SESSION_ID, sessionId);
-        
         _logger.debug("user session id is {} , online ticket {} ",sessionId,(onlineTicket == null ? "" : onlineTicket.getTicketId()));
         
         userInfo.setLastLoginTime(DateUtils.formatDateTime(new Date()));
@@ -189,7 +190,7 @@ public abstract class AbstractAuthenticationRealm {
 
         }
 
-        loginHistoryService.login(userInfo,sessionId, type, message, code, provider, browser, platform);
+        loginHistoryService.login(userInfo,sessionId, type, message, code, provider, browser, platform,sessionStatus);
         
         loginService.setLastLoginInfo(userInfo);
 

+ 5 - 5
maxkey-core/src/main/java/org/maxkey/persistence/db/LoginHistoryService.java

@@ -28,9 +28,9 @@ import org.springframework.jdbc.core.JdbcTemplate;
 public class LoginHistoryService {
     private static Logger _logger = LoggerFactory.getLogger(LoginHistoryService.class);
     
-    private static final String HISTORY_LOGIN_INSERT_STATEMENT = "insert into mxk_history_login (id , sessionid , uid , username , displayname , logintype , message , code , provider , sourceip , browser , platform , application , loginurl )values( ? , ? , ? , ? , ?, ? , ? , ?, ? , ? , ?, ? , ? , ?)";
+    private static final String HISTORY_LOGIN_INSERT_STATEMENT = "insert into mxk_history_login (id , sessionid , uid , username , displayname , logintype , message , code , provider , sourceip , browser , platform , application , loginurl , sessionstatus)values( ? , ? , ? , ? , ? , ?, ? , ? , ?, ? , ? , ?, ? , ? , ?)";
 
-    private static final String HISTORY_LOGOUT_UPDATE_STATEMENT = "update mxk_history_login set logouttime = ?  where  sessionid = ?";
+    private static final String HISTORY_LOGOUT_UPDATE_STATEMENT = "update mxk_history_login set logouttime = ? ,sessionstatus = 7 where  sessionid = ?";
 
     protected JdbcTemplate jdbcTemplate;
     
@@ -39,14 +39,14 @@ public class LoginHistoryService {
     }
     
     public void login(UserInfo userInfo,String sessionId,
-            String type, String message, String code, String provider,String browser, String platform) {
+            String type, String message, String code, String provider,String browser, String platform,int sessionStatus) {
         jdbcTemplate.update(HISTORY_LOGIN_INSERT_STATEMENT,
                 new Object[] { WebContext.genId(), sessionId, userInfo.getId(), userInfo.getUsername(),
                         userInfo.getDisplayName(), type, message, code, provider, userInfo.getLastLoginIp(), browser, platform,
-                        "Browser", WebContext.getRequest().getRequestURI() },
+                        "Browser", WebContext.getRequest().getRequestURI() , sessionStatus},
                 new int[] { Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
                         Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
-                        Types.VARCHAR, Types.VARCHAR });
+                        Types.VARCHAR, Types.VARCHAR ,Types.INTEGER});
         
 
     }

+ 5 - 1
maxkey-persistence/src/main/java/org/maxkey/persistence/mapper/HistoryLoginMapper.java

@@ -18,6 +18,8 @@
 package org.maxkey.persistence.mapper;
 
 
+import java.util.List;
+
 import org.apache.mybatis.jpa.persistence.IJpaBaseMapper;
 import org.maxkey.entity.HistoryLogin;
 
@@ -26,5 +28,7 @@ import org.maxkey.entity.HistoryLogin;
  *
  */
 public interface HistoryLoginMapper extends IJpaBaseMapper<HistoryLogin> {
-
+    
+    public List<HistoryLogin> queryOnlineSession(HistoryLogin historyLogin);
+    
 }

+ 5 - 0
maxkey-persistence/src/main/java/org/maxkey/persistence/service/HistoryLoginService.java

@@ -18,6 +18,7 @@
 package org.maxkey.persistence.service;
 
 import org.apache.mybatis.jpa.persistence.JpaBaseService;
+import org.apache.mybatis.jpa.persistence.JpaPageResults;
 import org.maxkey.entity.HistoryLogin;
 import org.maxkey.persistence.mapper.HistoryLoginMapper;
 import org.springframework.stereotype.Repository;
@@ -37,4 +38,8 @@ public class HistoryLoginService  extends JpaBaseService<HistoryLogin>{
 		// TODO Auto-generated method stub
 		return (HistoryLoginMapper)super.getMapper();
 	}
+	
+	public JpaPageResults<HistoryLogin> queryOnlineSession(HistoryLogin historyLogin) {
+	    return this.queryPageResults("queryOnlineSession",historyLogin);
+	}
 }

+ 27 - 0
maxkey-persistence/src/main/resources/org/maxkey/persistence/mapper/xml/mysql/HistoryLoginMapper.xml

@@ -63,6 +63,33 @@
     	order by logintime desc
     </select>
     
+    
+    <select id="queryOnlineSession" parameterType="HistoryLogin" resultType="HistoryLogin">
+        select 
+            sessionid id,
+            sessionid,
+            uid,
+            username,
+            displayname,
+            logintype,
+            message,
+            code,
+            provider,
+            sourceip,
+            browser,
+            platform,
+            application,
+            loginurl,
+            date_format(logintime, '%Y-%m-%d  %H:%i:%s') as logintime,
+            date_format(logouttime, '%Y-%m-%d  %H:%i:%s') as logouttime
+        from mxk_history_login
+        where   sessionstatus = 1
+        
+        <include refid="dao_where_statement"/>
+        
+        order by logintime desc
+    </select>
+    
     <update id="logout" parameterType="java.lang.String" >
     	update mxk_history_login set
 			logouttime			=	current_timestamp() 

+ 2 - 0
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/MaxKeyMvcConfig.java

@@ -150,6 +150,8 @@ public class MaxKeyMvcConfig implements WebMvcConfigurer {
                 .addPathPatterns("/profile/**")
                 .addPathPatterns("/safe/**")
                 .addPathPatterns("/historys/**")
+                .addPathPatterns("/loginsession/**")
+                .addPathPatterns("loginsession/loginSessionList/grid")
                 .addPathPatterns("/appList")
                 .addPathPatterns("/appList/**")
                 .addPathPatterns("/socialsignon/**")

+ 141 - 0
maxkey-webs/maxkey-web-maxkey/src/main/java/org/maxkey/web/historys/contorller/LoginSessionController.java

@@ -0,0 +1,141 @@
+/*
+ * Copyright [2020] [MaxKey of copyright http://www.maxkey.top]
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ 
+
+package org.maxkey.web.historys.contorller;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import org.apache.mybatis.jpa.persistence.JpaPageResults;
+import org.maxkey.authn.SigninPrincipal;
+import org.maxkey.authn.online.OnlineTicket;
+import org.maxkey.authn.online.OnlineTicketServices;
+import org.maxkey.constants.ConstantsOperateMessage;
+import org.maxkey.entity.HistoryLogin;
+import org.maxkey.entity.HistoryLoginApps;
+import org.maxkey.entity.HistoryLogs;
+import org.maxkey.entity.UserInfo;
+import org.maxkey.persistence.db.LoginHistoryService;
+import org.maxkey.persistence.db.LoginService;
+import org.maxkey.persistence.service.HistoryLoginAppsService;
+import org.maxkey.persistence.service.HistoryLoginService;
+import org.maxkey.persistence.service.HistorySystemLogsService;
+import org.maxkey.util.DateUtils;
+import org.maxkey.util.StringUtils;
+import org.maxkey.web.WebContext;
+import org.maxkey.web.message.Message;
+import org.maxkey.web.message.MessageType;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.propertyeditors.CustomDateEditor;
+import org.springframework.security.core.Authentication;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.InitBinder;
+import org.springframework.web.bind.annotation.ModelAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+/**
+ * 登录日志查询.
+ * 
+ * @author Crystal.sea
+ *
+ */
+
+@Controller
+@RequestMapping(value = { "/loginsession" })
+public class LoginSessionController {
+    static final Logger _logger = LoggerFactory.getLogger(LoginSessionController.class);
+
+    @Autowired
+    HistoryLoginService historyLoginService;
+    @Autowired
+    LoginService loginService;
+    
+    @Autowired
+    LoginHistoryService loginHistoryService;
+    
+    @Autowired
+    OnlineTicketServices onlineTicketServices;
+    
+    @RequestMapping(value = { "/loginSessionList" })
+    public String authList() {
+        return "historys/loginSessionList";
+    }
+
+    /**
+     * 查询登录日志.
+     * 
+     * @param logsAuth
+     * @return
+     */
+    @RequestMapping(value = { "/loginSessionList/grid" })
+    @ResponseBody
+    public JpaPageResults<HistoryLogin> loginSessionListGrid(@ModelAttribute("historyLogin") HistoryLogin historyLogin) {
+        _logger.debug("history/loginsession/ loginSessionListGrid() " + historyLogin);
+        historyLogin.setUid(WebContext.getUserInfo().getId());
+        return historyLoginService.queryOnlineSession(historyLogin);
+    }
+
+
+    
+    @ResponseBody
+    @RequestMapping(value="/terminate")  
+    public Message deleteUsersById(@RequestParam("id") String ids) {
+        _logger.debug(ids);
+        boolean isTerminated = false;
+        try {
+            OnlineTicket onlineTicket = null;
+            Authentication authentication = WebContext.getAuthentication();
+            if(authentication.getPrincipal() instanceof SigninPrincipal) {
+                SigninPrincipal signinPrincipal = (SigninPrincipal)authentication.getPrincipal();
+                //onlineTicket 
+                onlineTicket = signinPrincipal.getOnlineTicket();
+                
+            }
+            for(String sessionId : StringUtils.string2List(ids, ",")) {
+                _logger.trace("terminate session Id {} ",sessionId);
+                if(onlineTicket.getTicketId().contains(sessionId)) {
+                    //skip current session
+                    continue;
+                }
+                UserInfo userInfo = WebContext.getUserInfo();
+                String lastLogoffTime = DateUtils.formatDateTime(new Date());
+                loginService.setLastLogoffInfo(userInfo);
+                loginHistoryService.logoff(lastLogoffTime, sessionId);
+                onlineTicketServices.remove("OT-" + sessionId);
+            }
+            isTerminated = true;
+        }catch(Exception e) {
+            _logger.debug("terminate Exception .",e);
+        }
+        
+        if(isTerminated) {
+            return  new Message(WebContext.getI18nValue(ConstantsOperateMessage.DELETE_SUCCESS),MessageType.success);
+        } else {
+            return  new Message(WebContext.getI18nValue(ConstantsOperateMessage.DELETE_ERROR),MessageType.error);
+        }
+    }
+    @InitBinder
+    public void initBinder(WebDataBinder binder) {
+        SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtils.FORMAT_DATE_HH_MM_SS);
+        dateFormat.setLenient(false);
+        binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, true));
+    }
+}

+ 2 - 0
maxkey-webs/maxkey-web-maxkey/src/main/resources/messages/message.properties

@@ -217,6 +217,7 @@ button.text.select=\u8bf7\u9009\u62e9
 button.text.search=\u67e5\u8be2
 button.text.expandsearch=\u5c55\u5f00
 button.text.collapsesearch=\u6536\u7f29
+button.text.terminate=\u7EC8\u6B62
 
 forgotpassword.emailmobile=\u90ae\u7bb1\u6216\u624b\u673a
 forgotpassword.email=\u90ae\u7bb1
@@ -284,6 +285,7 @@ navs.setting.timetoken=\u65f6\u95f4\u4ee4\u724c
 navs.myprofile=\u6211\u7684\u8d44\u6599
 
 navs.audit=\u5ba1\u8ba1
+navs.audit.loginsession=\u4F1A\u8BDD
 navs.audit.login=\u767b\u5f55\u65e5\u5fd7
 navs.audit.signon=\u8bbf\u95ee\u65e5\u5fd7
 navs.audit.operation=\u7BA1\u7406\u65e5\u5fd7

+ 2 - 0
maxkey-webs/maxkey-web-maxkey/src/main/resources/messages/message_en.properties

@@ -216,6 +216,7 @@ button.text.select=Select
 button.text.search=Search
 button.text.expandsearch=Expand
 button.text.collapsesearch=Collapse
+button.text.terminate=Terminate
 
 forgotpassword.emailmobile=Email OR Mobile
 forgotpassword.email=Email
@@ -285,6 +286,7 @@ navs.setting.timetoken=Timetoken
 navs.myprofile=My Profile
 
 navs.audit=Audit
+navs.audit.loginsession=Session
 navs.audit.login=Login
 navs.audit.signon=Sign-on
 navs.audit.operation=Management

+ 2 - 0
maxkey-webs/maxkey-web-maxkey/src/main/resources/messages/message_zh_CN.properties

@@ -217,6 +217,7 @@ button.text.select=\u8bf7\u9009\u62e9
 button.text.search=\u67e5\u8be2
 button.text.expandsearch=\u5c55\u5f00
 button.text.collapsesearch=\u6536\u7f29
+button.text.terminate=\u7EC8\u6B62
 
 forgotpassword.emailmobile=\u90ae\u7bb1\u6216\u624b\u673a
 forgotpassword.email=\u90ae\u7bb1
@@ -284,6 +285,7 @@ navs.setting.timetoken=\u65f6\u95f4\u4ee4\u724c
 navs.myprofile=\u6211\u7684\u8d44\u6599
 
 navs.audit=\u5ba1\u8ba1
+navs.audit.loginsession=\u4F1A\u8BDD
 navs.audit.login=\u767b\u5f55\u65e5\u5fd7
 navs.audit.signon=\u8bbf\u95ee\u65e5\u5fd7
 navs.audit.operation=\u7BA1\u7406\u65e5\u5fd7

+ 98 - 0
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/historys/loginSessionList.ftl

@@ -0,0 +1,98 @@
+<!DOCTYPE HTML >
+<html>
+<head>
+	<#include  "../layout/header.ftl"/>
+	<#include  "../layout/common.cssjs.ftl"/>
+</head>
+<body>
+<#include  "../layout/top.ftl"/>
+<#include  "../layout/nav_primary.ftl"/>
+<div class="container">
+	<div id="tool_box">
+		<table  class="table table-bordered">
+			<tr>
+				<td  width="120px">
+				<@locale code="log.loginhistory.sourceIp"/>
+				</td>
+				<td  width="375px">
+					<form id="basic_search_form">
+				 			<input class="form-control" name="sourceIp" type="text" style ="width:150px;float:left;">
+				 			<input class="button btn btn-primary mr-3"  id="searchBtn" type="button" size="50" value="<@locale code="button.text.search"/>">
+				 			<input class="button btn btn-secondary"  id="advancedSearchExpandBtn" type="button" size="50"  value="<@locale code="button.text.expandsearch"/>" expandValue="<@locale code="button.text.expandsearch"/>"  collapseValue="<@locale code="button.text.collapsesearch"/>">
+					 	</form>
+				</td>
+				<td colspan="2"> 
+				    <div id="tool_box_right">
+					   <input id="deleteBtn" type="button" class="button btn btn-danger mr-3 "   
+					       value="<@locale code="button.text.terminate"/>" 
+					       wurl="<@base/>/loginsession/terminate" />
+				    </div>
+				</td>
+			</tr>
+		</table>
+ 		
+		
+ 	</div>
+ 	
+ 	<div id="advanced_search">
+ 		<form id="advanced_search_form">
+ 			<table   class="table table-bordered">
+			 <tr>
+	 				<td width="120px"><@locale code="common.text.startdate"/></td>
+		 			<td width="360px">
+		 				<input class="datetimepicker form-control" name="startDate" type="text" >
+		 			</td>
+		 			<td width="120px"><@locale code="common.text.enddate"/></td>
+		 			<td width="360px">
+						<input style="width:70%"  class="datetimepicker form-control"  type="text" id="endDate" name="endDate"  title="" value=""/>
+			 		</td>
+			 </tr>
+			</table>
+ 		</form>
+ 	</div>
+ 	
+<div class="mainwrap" id="main">
+
+	<table  data-url="<@base />/loginsession/loginSessionList/grid"
+			id="datagrid"
+			data-toggle="table"
+			data-classes="table table-bordered table-hover table-striped"
+			data-pagination="true"
+			data-click-to-select="true"
+			data-total-field="records"
+			data-page-list="[10, 25, 50, 100]"
+			data-search="false"
+			data-locale="zh-CN"
+			data-query-params="dataGridQueryParams"
+			data-query-params-type="pageSize"
+			data-side-pagination="server">
+		<thead>
+			<tr>
+			    <th data-checkbox="true"></th>
+				<th data-sortable="true" data-field="id"   data-visible="false"><@locale code="log.loginhistory.id"/></th>
+				<th data-field="sessionId"><@locale code="log.loginhistory.sessionId"/></th>
+				<th data-field="username"><@locale code="log.loginhistory.username"/></th>
+				<th data-field="displayName"><@locale code="log.loginhistory.displayName"/></th>
+				<th data-field="provider"><@locale code="log.loginhistory.provider"/></th>
+				<th data-field="message"><@locale code="log.loginhistory.message"/></th>
+				<th data-field="loginType"><@locale code="log.loginhistory.loginType"/></th>
+				<th data-field="sourceIp"><@locale code="log.loginhistory.sourceIp"/></th>
+				<th data-field="browser"><@locale code="log.loginhistory.browser"/></th>
+				<th data-field="loginTime"><@locale code="log.loginhistory.loginTime"/></th>
+				<th data-field="logoutTime"><@locale code="log.loginhistory.logoutTime"/></th>
+				<th data-field="platform"><@locale code="log.loginhistory.platform"/></th>
+				<th data-field="application" data-visible="false"><@locale code="log.loginhistory.application"/></th>
+				<th data-field="loginUrl" data-visible="false"><@locale code="log.loginhistory.loginUrl"/></th>
+				<th data-field="code" data-visible="false"><@locale code="log.loginhistory.code"/></th>
+				<th data-field="rpUserInfo" data-visible="false"><@locale code="log.loginhistory.rpUserInfo"/></th>
+	
+			</tr>
+		</thead>
+	</table>
+</div>
+</div>
+<div id="footer">
+	<#include   "../layout/footer.ftl"/>
+</div>
+</body>
+</html>

+ 6 - 0
maxkey-webs/maxkey-web-maxkey/src/main/resources/templates/views/layout/nav_primary.ftl

@@ -52,6 +52,12 @@
 			<li  id="nav_primay_15"  class="nav_primay_level primaryleft"  xpath="">
 				<a   href="<@base/>/historys/loginList"><@locale code="navs.audit"/></a>
 				<div id="nav_child_1501"  class="nav_second_child">
+				    <ul>
+                        <!--登录日志-->
+                        <li id="nav_second_1501" class="nav_second_level">
+                            <a   href="<@base/>/loginsession/loginSessionList"><@locale code="navs.audit.loginsession"/></a>
+                        </li>
+                    </ul>
 					<ul>
 						<!--登录日志-->
 						<li id="nav_second_1501" class="nav_second_level">