From b4f8168028a15616b7378d5eb957262920bed70e Mon Sep 17 00:00:00 2001 From: liu Date: Fri, 1 Dec 2023 14:11:24 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=85=B3=E4=BA=8E=E8=B6=85?= =?UTF-8?q?=E6=97=B6=E7=99=BB=E5=BD=95=E7=9A=84=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../supervision/config/JwtInterceptor.java | 29 ++-------- .../config/UserSingleLoginConfig.java | 53 +++++++++++++++++++ .../impl/MedicalRecManageServiceImpl.java | 5 +- .../controller/UserController.java | 17 +++++- .../java/com/supervision/util/UserUtil.java | 4 ++ 5 files changed, 80 insertions(+), 28 deletions(-) create mode 100644 virtual-patient-common/src/main/java/com/supervision/config/UserSingleLoginConfig.java diff --git a/virtual-patient-common/src/main/java/com/supervision/config/JwtInterceptor.java b/virtual-patient-common/src/main/java/com/supervision/config/JwtInterceptor.java index 36fc654b..220f1441 100644 --- a/virtual-patient-common/src/main/java/com/supervision/config/JwtInterceptor.java +++ b/virtual-patient-common/src/main/java/com/supervision/config/JwtInterceptor.java @@ -22,11 +22,9 @@ import java.util.concurrent.ConcurrentHashMap; @Slf4j public class JwtInterceptor implements HandlerInterceptor { - private static final ConcurrentHashMap singleLoginTokenCacheMap = new ConcurrentHashMap<>(); @Override - public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) { //请求消息头获取用户ID String token = request.getHeader("token"); @@ -44,7 +42,7 @@ public class JwtInterceptor implements HandlerInterceptor { // 校验token是否过期,如果过期了,需要提示过期重新登录 checkTokenExpire(jwt); // 校验是否重复登录 - checkSingleLogin(jwt); + UserSingleLoginConfig.checkSingleLogin(jwt); cacheAuth(jwt); return true; } @@ -57,6 +55,7 @@ public class JwtInterceptor implements HandlerInterceptor { HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } + private void checkTokenExpire(JWT jwt) { Object expireTime = jwt.getPayload("expireTime"); long l = Long.parseLong(String.valueOf(expireTime)); @@ -67,29 +66,7 @@ public class JwtInterceptor implements HandlerInterceptor { } } - private void checkSingleLogin(JWT currentJwt) { - Object id = currentJwt.getPayload("id"); - JWT singleLoginTokenCache = singleLoginTokenCacheMap.get(id); - if (Objects.isNull(singleLoginTokenCache)){ - singleLoginTokenCacheMap.put(id, currentJwt); - return; - } - // 然后将当前的expireTime和singleLoginTokenCache进行比较 - Object expireTime = singleLoginTokenCache.getPayload("expireTime"); - long singleLoginTokenCacheExpireTime = Long.parseLong(String.valueOf(expireTime)); - Object currentJwtExpireTimeObject = currentJwt.getPayload("expireTime"); - long currentJwtExpireTime = Long.parseLong(String.valueOf(currentJwtExpireTimeObject)); - if (singleLoginTokenCacheExpireTime == currentJwtExpireTime) { - // 如果相等,说明这个token就是最新的,直接放行 - return; - } else if (currentJwtExpireTime > singleLoginTokenCacheExpireTime) { - // 如果当前的超时时间要大于缓存的,说明重新登录了,这个时候要把最新的放到缓存中 - singleLoginTokenCacheMap.put(id, currentJwt); - } else { - // 走到这里,说明singleLoginTokenCache是最新的,说明当前请求的token就过期了 - throw new BusinessException("当前用户已在其他地方登录!"); - } - } + private void cacheAuth(JWT jwt) { try { diff --git a/virtual-patient-common/src/main/java/com/supervision/config/UserSingleLoginConfig.java b/virtual-patient-common/src/main/java/com/supervision/config/UserSingleLoginConfig.java new file mode 100644 index 00000000..fd56eab5 --- /dev/null +++ b/virtual-patient-common/src/main/java/com/supervision/config/UserSingleLoginConfig.java @@ -0,0 +1,53 @@ +package com.supervision.config; + +import cn.hutool.cache.CacheUtil; +import cn.hutool.cache.impl.TimedCache; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.jwt.JWT; +import com.supervision.exception.BusinessException; +import lombok.extern.slf4j.Slf4j; + +import java.util.Objects; +import java.util.concurrent.ConcurrentHashMap; + +@Slf4j +public class UserSingleLoginConfig { + + /** + * 创建缓存,过期时间为5分钟,如果5分钟内没有请求过来,就认为是超时 + */ + private static final TimedCache singleLoginTokenCacheMap = CacheUtil.newTimedCache(1000 * 5); + + static { + // 每秒钟扫描一次 + singleLoginTokenCacheMap.schedulePrune(1000); + } + + + public static void loginOrRefreshUser(String id, JWT jwt) { + singleLoginTokenCacheMap.put(id, jwt); + } + + public static void checkSingleLogin(JWT currentJwt) { + Object id = currentJwt.getPayload("id"); + JWT singleLoginTokenCache = singleLoginTokenCacheMap.get(id); + if (ObjectUtil.isEmpty(singleLoginTokenCache)) { + throw new BusinessException("用户已被踢下线或超时,请重新登录", 505); + } + // 然后将当前的expireTime和singleLoginTokenCache进行比较 + Object expireTime = singleLoginTokenCache.getPayload("expireTime"); + long singleLoginTokenCacheExpireTime = Long.parseLong(String.valueOf(expireTime)); + Object currentJwtExpireTimeObject = currentJwt.getPayload("expireTime"); + long currentJwtExpireTime = Long.parseLong(String.valueOf(currentJwtExpireTimeObject)); + if (singleLoginTokenCacheExpireTime == currentJwtExpireTime) { + // 如果相等,说明这个token就是最新的,直接放行 + return; + } else if (currentJwtExpireTime > singleLoginTokenCacheExpireTime) { + // 如果当前的超时时间要大于缓存的,说明重新登录了,这个时候要把最新的放到缓存中 + singleLoginTokenCacheMap.put(id, currentJwt); + } else { + // 走到这里,说明singleLoginTokenCache是最新的,说明当前用户请求了一个新的token,那么原来的用户就踢掉 + throw new BusinessException("当前用户已在其他地方登录!", 505); + } + } +} diff --git a/virtual-patient-manage/src/main/java/com/supervision/manage/service/impl/MedicalRecManageServiceImpl.java b/virtual-patient-manage/src/main/java/com/supervision/manage/service/impl/MedicalRecManageServiceImpl.java index 68a6fa1d..50b32845 100644 --- a/virtual-patient-manage/src/main/java/com/supervision/manage/service/impl/MedicalRecManageServiceImpl.java +++ b/virtual-patient-manage/src/main/java/com/supervision/manage/service/impl/MedicalRecManageServiceImpl.java @@ -154,6 +154,9 @@ public class MedicalRecManageServiceImpl implements MedicalRecManageService { public void modifyMedicalRec(MedicalRecManageVO reqVO) { // 首先修改病人 Patient patient = reqVO.getPatient(); + if (StrUtil.isBlank(patient.getId())){ + throw new BusinessException("病人ID不能为空"); + } patient.updateById(); // 病历不允许修改 MedicalRec medicalRec = Optional.ofNullable(medicalRecService.getById(reqVO.getId())).orElseThrow(() -> new BusinessException("未找到病历信息")); @@ -191,7 +194,7 @@ public class MedicalRecManageServiceImpl implements MedicalRecManageService { @Override public MedicalRecInfoVO queryMedicalRecInfo(String id) { - MedicalRec medicalRec = medicalRecService.getById(id); + MedicalRec medicalRec = Optional.ofNullable(medicalRecService.getById(id)).orElseThrow(() -> new BusinessException("未找到病历")); MedicalRecInfoVO medicalRecInfoVO = BeanUtil.toBean(medicalRec, MedicalRecInfoVO.class); medicalRecInfoVO.setDiseaseName(diseaseService.getById(medicalRec.getDiseaseId()).getDiseaseName()); // 病人基本信息 diff --git a/virtual-patient-web/src/main/java/com/supervision/controller/UserController.java b/virtual-patient-web/src/main/java/com/supervision/controller/UserController.java index a8633904..a1a11e6a 100644 --- a/virtual-patient-web/src/main/java/com/supervision/controller/UserController.java +++ b/virtual-patient-web/src/main/java/com/supervision/controller/UserController.java @@ -2,12 +2,15 @@ package com.supervision.controller; import cn.hutool.core.util.StrUtil; import cn.hutool.json.JSONUtil; +import cn.hutool.jwt.JWT; +import com.supervision.config.UserSingleLoginConfig; import com.supervision.domain.UserInfo; import com.supervision.exception.BusinessException; import com.supervision.model.User; import com.supervision.pojo.vo.LoginReqVO; import com.supervision.service.UserService; import com.supervision.util.TokenUtil; +import com.supervision.util.UserUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import lombok.RequiredArgsConstructor; @@ -36,6 +39,18 @@ public class UserController { if (!user.get().getPassword().equals(reqVO.getPassword())) { throw new BusinessException("密码错误"); } - return TokenUtil.creatToken(JSONUtil.toJsonStr(user.get())); + String token = TokenUtil.creatToken(JSONUtil.toJsonStr(user.get())); + // 将用户的token保存起来 + UserSingleLoginConfig.loginOrRefreshUser(user.get().getId(), JWT.create().parse(token)); + return token; } + + @ApiOperation("token心跳") + @PostMapping("keepaliveToken") + public void keepaliveToken() { + String token = UserUtil.getUserToken(); + UserSingleLoginConfig.loginOrRefreshUser(UserUtil.getUser().getId(), JWT.create().parse(token)); + } + + } diff --git a/virtual-patient-web/src/main/java/com/supervision/util/UserUtil.java b/virtual-patient-web/src/main/java/com/supervision/util/UserUtil.java index b730cba1..8b74842c 100644 --- a/virtual-patient-web/src/main/java/com/supervision/util/UserUtil.java +++ b/virtual-patient-web/src/main/java/com/supervision/util/UserUtil.java @@ -17,4 +17,8 @@ public class UserUtil { } return bean; } + + public static String getUserToken(){ + return ThreadCache.USER.get(); + } }