瀏覽代碼

新增登录状态字段

xusl 1 年之前
父節點
當前提交
e0cb0a1a3f

+ 5 - 0
backend/pom.xml

@@ -45,6 +45,11 @@
 
     <dependencies>
         <dependency>
+            <groupId>org.bouncycastle</groupId>
+            <artifactId>bcpkix-jdk15on</artifactId>
+            <version>1.68</version>
+        </dependency>
+        <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-dependencies</artifactId>
             <version>${spring-boot.version}</version>

+ 4 - 0
backend/src/main/java/com/jiayue/ssi/entity/SysUser.java

@@ -44,6 +44,10 @@ public class SysUser extends BaseEntity implements UserDetails {
      */
     private String status;
     /**
+     * 账号在线状态(0在线、1离线)
+     */
+    private String onlineStatus;
+    /**
      * 邮箱
      */
     private String mailbox;

+ 1 - 0
backend/src/main/java/com/jiayue/ssi/handler/CustomAuthenticationSuccessHandler.java

@@ -63,6 +63,7 @@ public class CustomAuthenticationSuccessHandler extends SavedRequestAwareAuthent
         sysUser.setErrNum(0);
         sysUser.setLockTime(0L);
         sysUser.setStatus("0");
+        sysUser.setOnlineStatus("0");
         // 加入登录IP和时间
         String ip = IPUtils.getIpAddr(request);
         sysUser.setLoginIp(ip);

+ 11 - 0
backend/src/main/java/com/jiayue/ssi/handler/CustomLogoutSuccessHandler.java

@@ -7,15 +7,19 @@ import com.jiayue.ssi.constant.LoginConstants;
 import com.jiayue.ssi.constant.SecretKeyConstants;
 import com.jiayue.ssi.entity.SysUser;
 import com.jiayue.ssi.factory.LoginFactory;
+import com.jiayue.ssi.service.SysUserService;
+import com.jiayue.ssi.util.IPUtils;
 import com.jiayue.ssi.util.ResponseVO;
 import com.jiayue.ssi.util.SM2CryptUtils;
 import com.jiayue.ssi.util.SecurityContextUtil;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.security.core.Authentication;
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.io.IOException;
+import java.util.Date;
 
 /**
  * 自定义退出处理类 返回成功
@@ -24,6 +28,9 @@ import java.io.IOException;
  */
 @Configuration
 public class CustomLogoutSuccessHandler implements org.springframework.security.web.authentication.logout.LogoutSuccessHandler {
+    @Autowired
+    SysUserService sysUserService;
+
     /**
      * 退出处理
      *
@@ -33,6 +40,10 @@ public class CustomLogoutSuccessHandler implements org.springframework.security.
     public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
             throws IOException, ServletException {
         SysUser sysUser = (SysUser)authentication.getPrincipal();
+        // 设置用户离线状态
+        sysUser.setOnlineStatus("1");
+        sysUserService.updateUser(sysUser);
+
         // 记录用户退出日志
         LoginFactory.recordLogininfor(sysUser.getUsername(), Constants.LOGIN_SUCCESS, "退出成功");
         // 将token存储内存中,便于重复登录比对

+ 1 - 1
backend/src/main/java/com/jiayue/ssi/job/AutoScanAccount.java

@@ -30,7 +30,7 @@ public class AutoScanAccount {
     SysPolicyService sysPolicyService;
 
     /**
-     * 每30分钟执行一次扫描
+     * 每10分钟执行一次扫描
      */
     @Scheduled(cron = "0 0/10 * * * ?")
     public void scanNotUsedAccount() throws Exception{

+ 1 - 1
backend/src/main/java/com/jiayue/ssi/job/AutoScanMemory.java

@@ -33,7 +33,7 @@ public class AutoScanMemory {
     /**
      * 每30分钟执行一次扫描
      */
-    @Scheduled(cron = "0 0/30 * * * ?")
+    @Scheduled(cron = "0 0/1 * * * ?")
     public void scanMemory() throws Exception{
         SysPolicy sysPolicy = sysPolicyService.getOne(new QueryWrapper<>());
         try {

+ 1 - 0
backend/src/main/resources/mapper/system/SysUserMapper.xml

@@ -16,6 +16,7 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
         <result property="errNum"       column="err_num"       />
         <result property="password"     column="password"     />
         <result property="status"       column="status"       />
+        <result property="onlineStatus"       column="online_status"       />
         <result property="lastUpdatePwdTime"       column="last_update_pwd_time"       />
         <result property="loginIp"       column="login_ip"       />
         <result property="loginDate"       column="login_date"       />

+ 48 - 33
ui/src/App.vue

@@ -15,45 +15,60 @@ export default {
     document.getElementById("app").oncontextmenu = function (e) {
       return false;
     };
-    // this.$nextTick(()=>{
-    //   document.onkeydown = function (e){
-    //     if (e && e.keyCode === 123){
-    //       e.returnValue = false;
-    //       return false;
-    //     }
-    //
+
+    // window.addEventListener("beforeunload", e => {
+    //   this.beforeunloadHandler(e)
+    //   let userAgent = navigator.userAgent
+    //   let isOpera = userAgent.indexOf("Opera") > -1;
+    //   if (isOpera) { //判断是否Opera浏览器
+    //     return "Opera"
+    //   }
+    //   if (userAgent.indexOf("Firefox") > -1) {
+    //     this.unloadHandler();
     //   }
-    //
-    // })
-    // window.addEventListener('beforeunload', e => this.beforeunloadHandler(e))
-    // window.addEventListener('unload', e => this.unloadHandler(e))
+    //   if (userAgent.indexOf("MSIE") > -1) {
+    //     this.unloadHandler();
+    //   }
+    // });
+    // window.addEventListener("unload", async e => {
+    //   this.unloadHandler(e)
+    // });
   },
-  // 解除窗口关闭[监听]事件
-  // destroyed() {
-  //   window.removeEventListener('beforeunload', e => this.beforeunloadHandler(e))
-  //   window.removeEventListener('unload', e => this.unloadHandler(e))
-  // },
   // methods: {
-  //   beforeunloadHandler(){
-  //     this._beforeUnload_time=new Date().getTime();
+  //   beforeunloadHandler(e) {
+  //     this._beforeUnload_time = new Date().getTime();
   //   },
-  //   unloadHandler(e){
-  //     this._gap_time=new Date().getTime()-this._beforeUnload_time;
+  //   unloadHandler(e) {
+  //     this._gap_time = new Date().getTime() - this._beforeUnload_time;
+  //
   //     //判断是窗口关闭还是刷新
-  //     if(this._gap_time<=5){
-  //       //如果是登录状态,关闭窗口前,移除用户
-  //       if(sessionStorage.getItem('jy')!=null){
-  //         this.$axios.post(
-  //           '/logout', {}
-  //         ).then((res) => {
-  //           this.$message.success(res.data)
-  //           removeToken()
-  //           //注销返回自己的登录页
-  //           this.$router.push(`/login?redirect=${this.$route.fullPath}`)
-  //         })
-  //       }
+  //     localStorage.setItem('time', this._gap_time)
+  //     console.log(this._gap_time, 333333)
+  //     if (this._gap_time <= 5) {
+  //       console.log(this._gap_time, 333333)
+  //       // // 发送设置同步 (退出登陆的api)
+  //       // this.$store.dispatch('LogOut').then(() => {
+  //       //   location.href = '/index';
+  //       // })
+  //
+  //
+  //       this.$axios.post(
+  //         '/logout', {}
+  //       ).then((res) => {
+  //         this.$message.success(res.data)
+  //         removeToken()
+  //         //注销返回自己的登录页
+  //         this.$router.push(`/login?redirect=${this.$route.fullPath}`)
+  //       })
+  //     } else {
   //     }
-  //   }
+  //   },
+  // },
+  // destroyed() {
+  //   window.removeEventListener("beforeunload", e =>
+  //     this.beforeunloadHandler(e)
+  //   );
+  //   window.removeEventListener("unload", e => this.unloadHandler(e));
   // }
 }
 </script>

+ 1 - 1
ui/src/directive/permission/hasPermi.js

@@ -12,7 +12,7 @@ export default {
     const all_permission = "*:*:*";
     // const permissions = store.getters && store.getters.permissions
     // 用户信息解密
-    let decryptUserInfo = userinfoDecrypt(sessionStorage.getItem('active'))
+    let decryptUserInfo = userinfoDecrypt(localStorage.getItem('active'))
     const permissions = JSON.parse(decryptUserInfo).permissions
     if (value && value instanceof Array && value.length > 0) {
       const permissionFlag = value

+ 1 - 1
ui/src/layout/components/Navbar.vue

@@ -186,7 +186,7 @@ export default {
         user = res.data.sysUser
         // 用户信息+菜单权限加密存储
         let encryptUserInfo = userinfoEncrypt(JSON.stringify(res.data))
-        sessionStorage.setItem('active', encryptUserInfo)
+        localStorage.setItem('active', encryptUserInfo)
         if (user.lastUpdatePwdTime == null) {
           this.$message({
             type: 'warning',

+ 2 - 2
ui/src/permission.js

@@ -17,7 +17,7 @@ router.beforeEach(async (to, from, next) => {
   NProgress.start()
   // set page title
   document.title = getPageTitle(to.meta.title)
-  if (sessionStorage.getItem('jy')) {
+  if (localStorage.getItem('jy')) {
     if (to.path === '/login') {
       // if is logged in, redirect to the home page
       next({ path: '/dashboard' })
@@ -40,7 +40,7 @@ router.beforeEach(async (to, from, next) => {
       if (to.path !=='/dashboard' && to.path !=='/user/profile'){
         // 用户信息解密
         // let decryptUserInfo = userinfoDecrypt(store.getters.userinfo)
-        let decryptUserInfo = userinfoDecrypt(sessionStorage.getItem('active'))
+        let decryptUserInfo = userinfoDecrypt(localStorage.getItem('active'))
         let user = JSON.parse(decryptUserInfo).sysUser
         if (user.lastUpdatePwdTime==null){
           Message({

+ 2 - 2
ui/src/utils/auth.js

@@ -13,8 +13,8 @@ export function setToken(token) {
 }
 
 export function removeToken() {
-  sessionStorage.removeItem('jy')
-  sessionStorage.removeItem('active')
+  localStorage.removeItem('jy')
+  localStorage.removeItem('active')
   store.dispatch('tagsView/delAllCachedViews')
   store.dispatch('tagsView/delAllVisitedViews')
 }

+ 4 - 4
ui/src/utils/request.js

@@ -55,8 +55,8 @@ service.interceptors.request.use(
       }
     }
 
-    if (sessionStorage.getItem("jy")!=="undefined" && sessionStorage.getItem("jy")!==undefined && sessionStorage.getItem("jy")!=null) { // 判断是否存在token,如果存在的话,则每个http header都加上token
-      let tokenStr = sessionStorage.getItem("jy")
+    if (localStorage.getItem("jy")!=="undefined" && localStorage.getItem("jy")!==undefined && localStorage.getItem("jy")!=null) { // 判断是否存在token,如果存在的话,则每个http header都加上token
+      let tokenStr = localStorage.getItem("jy")
 
       config.headers['Authorization'] = tokenStr.split("&")[0]
       config.headers['JySign'] = tokenStr.split("&")[1]
@@ -187,7 +187,7 @@ service.interceptors.response.use(
               // 替换token
               let tokenStr = doEncrypt(res.data)
               let sign = doSign(res.data)
-              sessionStorage.setItem('jy', tokenStr+'&'+sign)
+              localStorage.setItem('jy', tokenStr+'&'+sign)
               // Vue.prototype.$axios(error.response.config)
               // 重新请求接口 前过期的接口
               error.config.headers.Authorization = res.data;
@@ -211,7 +211,7 @@ service.interceptors.response.use(
             // 正在刷新token ,把后来的接口缓冲起来
             return new Promise((resolve) => {
               requests.push(() => {
-                error.config.headers.Authorization = sessionStorage.getItem('jy');
+                error.config.headers.Authorization = localStorage.getItem('jy');
                 resolve(Vue.prototype.$axios.request(error.config));
               });
             })

+ 1 - 1
ui/src/views/bizManager/nwp/charts/index.vue

@@ -256,7 +256,7 @@
       }
     },
     mounted() {
-      if(sessionStorage.getItem('styleSwitch') === 'blue'){
+      if(localStorage.getItem('styleSwitch') === 'blue'){
         this.lineColor = 'white'
       }else{
         this.lineColor = '#3b3b3b'

+ 1 - 1
ui/src/views/login/index.vue

@@ -291,7 +291,7 @@ export default {
           this.$axios.post('/user/login', param).then((res) => {
             let tokenStr = doEncrypt(res.data)
             let sign = doSign(res.data)
-            sessionStorage.setItem('jy', tokenStr + '&' + sign)
+            localStorage.setItem('jy', tokenStr + '&' + sign)
             // 清空路由菜单
             store.commit('SET_R', [])
             this.$router.push('/dashboard')

+ 2 - 2
ui/src/views/sysManager/sysPolicy/index.vue

@@ -12,7 +12,7 @@
               <el-checkbox v-for="(item,index) in passwordRuleList" :key="index" :label="item.value" >{{item.label}}</el-checkbox>
             </el-checkbox-group>
           </el-form-item>
-          <el-form-item label="扫描未使用的账号(设定月个数)" prop="scanAccount">
+          <el-form-item label="账号未使用的月数设置" prop="scanAccount">
             <el-input v-model="form.scanAccount" style="width: 240px"></el-input>
           </el-form-item>
           <el-form-item label="非活动状态登出系统(设定分钟数)" prop="inactiveLogout">
@@ -119,7 +119,7 @@ export default {
         ],
         scanAccount: [
           { required: true, message: "扫描未使用的账号不能为空", trigger: "blur" },
-          { pattern: /^([0-9]|(1[0-2]))$/, message: "请输入0-12整数", trigger: "blur"}
+          { pattern: /^([1-3])$/, message: "请输入1-3整数", trigger: "blur"}
         ],
         loginLock: [
           { required: true, message: "登录失败锁定时长不能为空", trigger: "blur" },

+ 14 - 1
ui/src/views/sysManager/userManager/index.vue

@@ -726,7 +726,13 @@ export default {
         });
         return
       }
-
+      if (_selectData.status == 2) {
+        this.$message({
+          type: 'warning',
+          message: '注销的账号不能操作!'
+        });
+        return
+      }
       this.form = _selectData;
       this.open = true;
       this.title = "修改用户";
@@ -742,6 +748,13 @@ export default {
         });
         return
       }
+      if (_selectData.status == 2) {
+        this.$message({
+          type: 'warning',
+          message: '注销的账号不能操作!'
+        });
+        return
+      }
       if (_selectData.status !== '1') {
         this.$message({
           type: 'warning',

+ 1 - 1
ui/src/views/sysManager/userManager/profile/index.vue

@@ -54,7 +54,7 @@ export default {
   },
   created() {
     // 用户信息解密
-    let decryptUserInfo = userinfoDecrypt(sessionStorage.getItem('active'))
+    let decryptUserInfo = userinfoDecrypt(localStorage.getItem('active'))
     this.user = JSON.parse(decryptUserInfo).sysUser
   },
   methods: {

+ 1 - 1
ui/src/views/sysManager/userManager/profile/resetPwd.vue

@@ -120,7 +120,7 @@ export default {
           })
 
           // 用户信息解密
-          let decryptUserInfo = userinfoDecrypt(sessionStorage.getItem('active'))
+          let decryptUserInfo = userinfoDecrypt(localStorage.getItem('active'))
           this.user = JSON.parse(decryptUserInfo).sysUser
           const param = {
             id: this.user.id,