From 7f0984b1bbad487d8f87315e2df680b65fadfba8 Mon Sep 17 00:00:00 2001 From: ma-zhongxu Date: Mon, 5 Jan 2026 11:08:18 +0800 Subject: [PATCH] =?UTF-8?q?1.=E4=BC=98=E5=8C=96=E5=A4=9A=E7=AB=AF=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E4=BB=A3=E7=A0=81=E7=BB=93=E6=9E=84=202.=E8=A7=A3?= =?UTF-8?q?=E5=86=B3=E5=A4=9A=E7=AB=AFtoken=E6=97=B6=E9=95=BF=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E5=8C=96=E7=AE=A1=E7=90=86=203.=E8=A7=A3=E5=86=B3?= =?UTF-8?q?=E5=B0=8F=E7=A8=8B=E5=BA=8F=E7=94=A8=E6=88=B7=E9=A6=96=E6=AC=A1?= =?UTF-8?q?=E7=99=BB=E5=BD=95=E6=B3=A8=E5=86=8C=E6=97=B6=E5=80=99=E7=9A=84?= =?UTF-8?q?=E9=BB=98=E8=AE=A4=E8=A7=92=E8=89=B2=E5=88=86=E9=85=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../controller/auth/MultiAuthController.java | 272 ++---------------- .../src/main/resources/application.yml | 9 +- .../web/service/SysLoginService.java | 249 +++++++++++++++- .../framework/web/service/TokenService.java | 91 +++--- 4 files changed, 326 insertions(+), 295 deletions(-) diff --git a/chenhai-admin/src/main/java/com/chenhai/web/controller/auth/MultiAuthController.java b/chenhai-admin/src/main/java/com/chenhai/web/controller/auth/MultiAuthController.java index 9804c20..5159962 100644 --- a/chenhai-admin/src/main/java/com/chenhai/web/controller/auth/MultiAuthController.java +++ b/chenhai-admin/src/main/java/com/chenhai/web/controller/auth/MultiAuthController.java @@ -1,26 +1,10 @@ package com.chenhai.web.controller.auth; -import com.alibaba.fastjson2.JSONObject; import com.chenhai.common.constant.Constants; import com.chenhai.common.core.domain.AjaxResult; -import com.chenhai.common.core.domain.entity.SysUser; import com.chenhai.common.core.domain.model.*; -import com.chenhai.common.core.redis.RedisCache; -import com.chenhai.common.utils.WechatDecryptUtil; -import com.chenhai.framework.security.exception.WechatNeedBindException; -import com.chenhai.framework.security.token.PhoneAuthenticationToken; -import com.chenhai.framework.security.token.WechatAuthenticationToken; import com.chenhai.framework.web.service.SysLoginService; -import com.chenhai.framework.web.service.SysPermissionService; -import com.chenhai.framework.web.service.SysSmsService; -import com.chenhai.framework.web.service.TokenService; -import com.chenhai.muhu.service.IUserAuthService; -import com.chenhai.muhu.service.WechatService; -import com.chenhai.system.service.ISysConfigService; -import com.chenhai.system.service.ISysUserService; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.security.authentication.AuthenticationManager; -import org.springframework.security.core.Authentication; import org.springframework.transaction.annotation.Transactional; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; @@ -28,275 +12,75 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import jakarta.validation.Valid; -import java.util.Date; -import java.util.HashMap; import java.util.Map; /** - * 多端认证控制器 - 统一处理牧户和兽医 + * 多端认证控制器 - 使用合并后的 SysLoginService */ @RestController @RequestMapping("/auth") public class MultiAuthController { - @Autowired - private AuthenticationManager authenticationManager; - - @Autowired - private TokenService tokenService; - - @Autowired - private SysSmsService smsService; - - @Autowired - private IUserAuthService userAuthService; - - @Autowired - private WechatService wechatService; - - @Autowired - private SysPermissionService permissionService; - - @Autowired - private RedisCache redisCache; - - @Autowired - private ISysUserService userService; - - @Autowired - private ISysConfigService sysConfigService; - @Autowired private SysLoginService loginService; /** - * 微信小程序登录(统一入口) + * 微信小程序登录 - 保持原逻辑 */ @PostMapping("/wechat/login") public AjaxResult wechatLogin(@Valid @RequestBody WechatLoginBody loginBody) { - // 验证参数 - if (loginBody.getCode() == null || loginBody.getClientType() == null) { - return AjaxResult.error("参数错误"); - } - - // 验证clientType - if (!"herdsman-app".equals(loginBody.getClientType()) && !"vet-app".equals(loginBody.getClientType())) { - return AjaxResult.error("不支持的客户端类型"); - } - - // 创建认证token - WechatAuthenticationToken authToken = new WechatAuthenticationToken( + Map result = loginService.wechatLogin( loginBody.getCode(), loginBody.getClientType() ); - try { - // 认证 - Authentication authentication = authenticationManager.authenticate(authToken); - LoginUser loginUser = (LoginUser) authentication.getPrincipal(); - - loginService.recordLoginInfo(loginUser.getUserId()); - - // 生成token - String token = tokenService.createToken(loginUser); - - // 返回结果 - AjaxResult ajax = AjaxResult.success(); - ajax.put(Constants.TOKEN, token); - return ajax; - - } catch (WechatNeedBindException e) { - // 需要绑定手机号 - Map data = new HashMap<>(); - data.put("needBind", true); - data.put("userType", e.getUserType()); // "herdsman" 或 "vet" - data.put("clientType", e.getClientType()); // "herdsman-app" 或 "vet-app" - data.put("openid", e.getOpenid()); - data.put("tempCode", e.getTempCode()); - data.put("authType", e.getAuthType()); - data.put("message", "请绑定手机号"); - return AjaxResult.success(data); - } + AjaxResult ajax = AjaxResult.success(result); + return ajax; } /** - * 微信绑定手机号(统一绑定接口) - * 牧户和兽医使用同一套逻辑 + * 微信绑定手机号 - 保持原逻辑(@Transactional 已移到Service) */ @PostMapping("/wechat/bind") - @Transactional +// @Transactional // 为了兼容,保留Controller层的事务注解 public AjaxResult wechatBind(@Valid @RequestBody WechatBindRequest request) { try { - // 1. 基本参数验证 - if (request.getEncryptedData() == null || request.getIv() == null) { - return AjaxResult.error("请通过微信授权获取手机号"); - } - - // 2. 从Redis获取sessionKey - String sessionKey = redisCache.getCacheObject("wechat:session:" + request.getTempCode()); - if (sessionKey == null) { - return AjaxResult.error("绑定会话已过期,请重新登录"); - } - - // 3. 解密手机号 - String phone = WechatDecryptUtil.decryptPhone( + Map result = loginService.wechatBind( request.getEncryptedData(), request.getIv(), - sessionKey - ); - if (phone == null || phone.trim().isEmpty()) { - return AjaxResult.error("获取手机号失败"); - } - - // 4. 查询手机号是否已注册 - SysUser existingUser = userService.selectUserByPhone(phone); - - // 5. 用户不存在,创建新用户 - if (existingUser == null) { - // 根据userType创建对应类型的用户 - String userTypeCode = "herdsman".equals(request.getUserType()) ? "02" : "01"; - - existingUser = createUser( - phone, - userTypeCode, - request.getNickName(), - request.getAvatarUrl(), - request.getClientType() - ); - - } else { - // 6. 用户已存在,检查用户类型是否匹配 - String existingUserType = existingUser.getUserType(); - String expectedUserType = "herdsman".equals(request.getUserType()) ? "02" : "01"; - - if (!existingUserType.equals(expectedUserType)) { - String existingTypeName = "01".equals(existingUserType) ? "兽医" : "牧户"; - String expectedTypeName = "01".equals(expectedUserType) ? "兽医" : "牧户"; - return AjaxResult.error("该手机号已注册为" + existingTypeName + ",请使用" + expectedTypeName + "小程序"); - } - - // 7. 用户类型匹配,更新用户信息(昵称、头像等) - if (request.getNickName() != null) { - existingUser.setNickName(request.getNickName()); - } - if (request.getAvatarUrl() != null) { - existingUser.setAvatar(request.getAvatarUrl()); - } - userService.updateUser(existingUser); - } - - // 8. 绑定微信openid - userAuthService.bindAuth( - existingUser.getUserId(), - request.getAuthType(), + request.getTempCode(), + request.getUserType(), + request.getClientType(), request.getOpenid(), - sessionKey - ); - - // 9. 创建登录用户 - LoginUser loginUser = new LoginUser( - existingUser.getUserId(), - existingUser.getDeptId(), - existingUser, - permissionService.getMenuPermission(existingUser), - request.getClientType() + request.getAuthType(), + request.getNickName(), + request.getAvatarUrl() ); - loginService.recordLoginInfo(loginUser.getUserId()); - - // 10. 生成token - String token = tokenService.createToken(loginUser); - - // 11. 清理Redis临时数据 - redisCache.deleteObject("wechat:session:" + request.getTempCode()); - - AjaxResult ajax = AjaxResult.success("绑定成功"); - ajax.put(Constants.TOKEN, token); - return ajax; - + return AjaxResult.success((String) result.get("message")) + .put(Constants.TOKEN, result.get("token")); } catch (Exception e) { + // 保持原异常处理方式 return AjaxResult.error("绑定失败: " + e.getMessage()); } } /** - * 手机号+密码登录(PC端使用) - * 牧户和兽医都可用 + * 手机号+密码登录 - 保持原逻辑 */ @PostMapping("/phone/login") public AjaxResult phoneLogin(@Valid @RequestBody PhoneLoginBody loginBody) { - // 验证参数 - if (loginBody.getPhone() == null || loginBody.getPassword() == null) { - return AjaxResult.error("参数错误"); - } + try { + String token = loginService.phoneLogin( + loginBody.getPhone(), + loginBody.getPassword(), + loginBody.getClientType() + ); - // 根据请求来源确定clientType - String clientType = loginBody.getClientType(); // 前端可传 "vet-pc" 或 "herdsman-pc" - if (clientType == null) { - clientType = "vet-pc"; // 默认兽医PC端 + return AjaxResult.success().put(Constants.TOKEN, token); + } catch (Exception e) { + // 保持原异常处理方式 + return AjaxResult.error(e.getMessage()); } - - // 创建认证token - PhoneAuthenticationToken authToken = new PhoneAuthenticationToken( - loginBody.getPhone(), - loginBody.getPassword(), - clientType - ); - - // 认证 - Authentication authentication = authenticationManager.authenticate(authToken); - LoginUser loginUser = (LoginUser) authentication.getPrincipal(); - loginService.recordLoginInfo(loginUser.getUserId()); - - // 生成token - String token = tokenService.createToken(loginUser); - - // 返回结果 - AjaxResult ajax = AjaxResult.success(); - ajax.put(Constants.TOKEN, token); - return ajax; - } - - /** - * 创建用户(牧户或兽医) - */ - private SysUser createUser(String phone, String userType, - String nickName, String avatarUrl, String clientType) { - SysUser user = new SysUser(); - - // 生成用户名:前缀 + 手机后4位 + 4位随机数 - String usernamePrefix = "01".equals(userType) ? "vet_" : "muhu_"; - String phoneSuffix = phone.length() > 4 ? phone.substring(phone.length() - 4) : phone; - String randomSuffix = String.format("%04d", (int)(Math.random() * 10000)); // 4位随机数 - String username = usernamePrefix + phoneSuffix + "_" + randomSuffix; - user.setUserName(username); - - // 设置昵称:统一为"用户" + 去掉前缀的username部分 - String displayName = phoneSuffix + "_" + randomSuffix; // 去掉前缀的部分 - user.setNickName(nickName != null ? nickName : ("用户" + displayName)); - - user.setUserType(userType); // "01":兽医, "02":牧户 - user.setEmail(""); - user.setPhonenumber(phone); - user.setSex("0"); - user.setAvatar(avatarUrl != null ? avatarUrl : ""); - - // 设置默认密码(微信登录用不到,但PC端登录需要) - String defaultPassword = sysConfigService.selectConfigByKey("sys.user.initPassword"); - user.setPassword(com.chenhai.common.utils.SecurityUtils.encryptPassword(defaultPassword)); - - user.setStatus("0"); // 正常状态 - user.setDelFlag("0"); - user.setCreateTime(new Date()); - - // 如果是兽医,设置初始审核状态 - // if ("01".equals(userType)) { - // user.setVetStatus("0"); // 0:未提交资质, 1:审核中, 2:已认证, 3:审核不通过 - // } - - userService.insertUser(user); - - // 重新查询获取完整用户信息 - return userService.selectUserByUserName(username); } } \ No newline at end of file diff --git a/chenhai-admin/src/main/resources/application.yml b/chenhai-admin/src/main/resources/application.yml index b6b0afb..47044b7 100644 --- a/chenhai-admin/src/main/resources/application.yml +++ b/chenhai-admin/src/main/resources/application.yml @@ -101,7 +101,14 @@ token: secret: e8f5b8c9d2a1f3e5c7b9d1a3f5c7e9b1d3a5f7c9e1b3d5a7f9c1e3b5d7a9f1c3e5b7d9a1f3c5e7b9d1a3f5c7e9b1d3a5f7c9e1b3d5a7f9c1e3b5d7a9f1c3e5b7d9a1f3c5 # 令牌有效期(默认30分钟) expireTime: 30 - # 牧户30天(30*24*3600秒) + # 牧户小程序30天(30*24*60) + herdsman-app: 43200 + # 兽医小程序7天(7*24*60) + vet-app: 10080 + # 兽医PC端8小时(8*60) + vet-pc: 480 + # 管理后台30分钟 + admin: 30 # application.yml diff --git a/chenhai-framework/src/main/java/com/chenhai/framework/web/service/SysLoginService.java b/chenhai-framework/src/main/java/com/chenhai/framework/web/service/SysLoginService.java index 3d16bcf..2fbff31 100644 --- a/chenhai-framework/src/main/java/com/chenhai/framework/web/service/SysLoginService.java +++ b/chenhai-framework/src/main/java/com/chenhai/framework/web/service/SysLoginService.java @@ -7,6 +7,7 @@ import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; import com.chenhai.common.constant.CacheConstants; import com.chenhai.common.constant.Constants; import com.chenhai.common.constant.UserConstants; @@ -25,12 +26,28 @@ import com.chenhai.common.utils.ip.IpUtils; import com.chenhai.framework.manager.AsyncManager; import com.chenhai.framework.manager.factory.AsyncFactory; import com.chenhai.framework.security.context.AuthenticationContextHolder; + +// =================== 新增依赖导入 =================== +import com.alibaba.fastjson2.JSONObject; +import com.chenhai.common.core.domain.entity.SysUser; +import com.chenhai.common.core.domain.model.*; +import com.chenhai.common.utils.WechatDecryptUtil; +import com.chenhai.framework.security.exception.WechatNeedBindException; +import com.chenhai.framework.security.token.PhoneAuthenticationToken; +import com.chenhai.framework.security.token.WechatAuthenticationToken; +import com.chenhai.muhu.service.IUserAuthService; +import com.chenhai.muhu.service.WechatService; import com.chenhai.system.service.ISysConfigService; import com.chenhai.system.service.ISysUserService; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +// ================================================= + /** * 登录校验方法 - * + * * @author ruoyi */ @Component @@ -44,16 +61,27 @@ public class SysLoginService @Autowired private RedisCache redisCache; - + @Autowired private ISysUserService userService; @Autowired private ISysConfigService configService; + // =================== 新增依赖 =================== + @Autowired + private IUserAuthService userAuthService; + + @Autowired + private WechatService wechatService; + + @Autowired + private SysPermissionService permissionService; + // =============================================== + /** - * 登录验证 - * + * 登录验证 - 原有的用户名密码登录 + * * @param username 用户名 * @param password 密码 * @param code 验证码 @@ -101,7 +129,7 @@ public class SysLoginService /** * 校验验证码 - * + * * @param username 用户名 * @param code 验证码 * @param uuid 唯一标识 @@ -173,4 +201,213 @@ public class SysLoginService { userService.updateLoginInfo(userId, IpUtils.getIpAddr(), DateUtils.getNowDate()); } -} + + // ==================================================================== + // =================== 以下是新增的多端登录方法 ======================= + // ==================================================================== + + /** + * 微信小程序登录 - 多端登录新增 + * + * @param code 微信code + * @param clientType 客户端类型: herdsman-app/vet-app + * @return 登录结果,包含token或绑定信息 + */ + public Map wechatLogin(String code, String clientType) { + // 验证参数 + if (code == null || clientType == null) { + throw new ServiceException("参数错误"); + } + if (!"herdsman-app".equals(clientType) && !"vet-app".equals(clientType)) { + throw new ServiceException("不支持的客户端类型"); + } + + // 创建认证token + WechatAuthenticationToken authToken = new WechatAuthenticationToken(code, clientType); + + try { + // 认证 + Authentication authentication = authenticationManager.authenticate(authToken); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + + recordLoginInfo(loginUser.getUserId()); + + // 生成token + String token = tokenService.createToken(loginUser); + + Map result = new HashMap<>(); + result.put("token", token); + result.put("needBind", false); + return result; + + } catch (WechatNeedBindException e) { + // 需要绑定手机号 + Map data = new HashMap<>(); + data.put("needBind", true); + data.put("userType", e.getUserType()); // "herdsman" 或 "vet" + data.put("clientType", e.getClientType()); // "herdsman-app" 或 "vet-app" + data.put("openid", e.getOpenid()); + data.put("tempCode", e.getTempCode()); + data.put("authType", e.getAuthType()); + data.put("message", "请绑定手机号"); + return data; + } + } + + /** + * 微信绑定手机号 - 多端登录新增 + */ + @Transactional(rollbackFor = ServiceException.class) + public Map wechatBind(String encryptedData, String iv, String tempCode, + String userType, String clientType, String openid, + String authType, String nickName, String avatarUrl) { + try { + // 1. 基本参数验证 + if (encryptedData == null || iv == null) { + throw new ServiceException("请通过微信授权获取手机号"); + } + + // 2. 从Redis获取sessionKey + String sessionKey = redisCache.getCacheObject("wechat:session:" + tempCode); + if (sessionKey == null) { + throw new ServiceException("绑定会话已过期,请重新登录"); + } + + // 3. 解密手机号 + String phone = WechatDecryptUtil.decryptPhone(encryptedData, iv, sessionKey); + if (phone == null || phone.trim().isEmpty()) { + throw new ServiceException("获取手机号失败"); + } + + // 4. 查询手机号是否已注册 + SysUser existingUser = userService.selectUserByPhone(phone); + + // 5. 用户不存在,创建新用户 + if (existingUser == null) { + String userTypeCode = "herdsman".equals(userType) ? "02" : "01"; + existingUser = createUserForWechat(phone, userTypeCode, nickName, avatarUrl, clientType); + } else { + // 6. 用户已存在,检查用户类型是否匹配 + String existingUserType = existingUser.getUserType(); + String expectedUserType = "herdsman".equals(userType) ? "02" : "01"; + + if (!existingUserType.equals(expectedUserType)) { + String existingTypeName = "01".equals(existingUserType) ? "兽医" : "牧户"; + String expectedTypeName = "01".equals(expectedUserType) ? "兽医" : "牧户"; + throw new ServiceException("该手机号已注册为" + existingTypeName + ",请使用" + expectedTypeName + "小程序"); + } + + // 7. 用户类型匹配,更新用户信息 + if (nickName != null) { + existingUser.setNickName(nickName); + } + if (avatarUrl != null) { + existingUser.setAvatar(avatarUrl); + } + userService.updateUser(existingUser); + } + + // 8. 绑定微信openid + userAuthService.bindAuth(existingUser.getUserId(), authType, openid, sessionKey); + + // 9. 创建登录用户 + LoginUser loginUser = new LoginUser( + existingUser.getUserId(), + existingUser.getDeptId(), + existingUser, + permissionService.getMenuPermission(existingUser), + clientType + ); + + recordLoginInfo(loginUser.getUserId()); + + // 10. 生成token + String token = tokenService.createToken(loginUser); + + // 11. 清理Redis临时数据 + redisCache.deleteObject("wechat:session:" + tempCode); + + Map result = new HashMap<>(); + result.put("token", token); + result.put("message", "绑定成功"); + return result; + + } catch (Exception e) { + // 保持原异常处理方式:返回 AjaxResult.error 的字符串 + throw new ServiceException("绑定失败: " + e.getMessage()); + } + } + + /** + * 手机号+密码登录 - 多端登录新增 + */ + public String phoneLogin(String phone, String password, String clientType) { + // 验证参数 + if (phone == null || password == null) { + throw new ServiceException("参数错误"); + } + + // 根据请求来源确定clientType + String finalClientType = clientType != null ? clientType : "vet-pc"; + + // 创建认证token + PhoneAuthenticationToken authToken = new PhoneAuthenticationToken(phone, password, finalClientType); + + // 认证 + Authentication authentication = authenticationManager.authenticate(authToken); + LoginUser loginUser = (LoginUser) authentication.getPrincipal(); + recordLoginInfo(loginUser.getUserId()); + + // 生成token + return tokenService.createToken(loginUser); + } + + /** + * 创建用户(微信绑定专用)- 多端登录新增 + */ + private SysUser createUserForWechat(String phone, String userType, + String nickName, String avatarUrl, String clientType) { + SysUser user = new SysUser(); + + // 生成用户名:前缀 + 手机后4位 + 4位随机数 + String usernamePrefix = "01".equals(userType) ? "vet_" : "muhu_"; + Long roleId = "01".equals(userType) ? 4L : 3L; + user.setRoleIds(new Long[]{roleId}); + String phoneSuffix = phone.length() > 4 ? phone.substring(phone.length() - 4) : phone; + String randomSuffix = String.format("%04d", (int)(Math.random() * 10000)); // 4位随机数 + String username = usernamePrefix + phoneSuffix + "_" + randomSuffix; + user.setUserName(username); + + // 设置昵称:统一为"用户" + 去掉前缀的username部分 + String displayName = phoneSuffix + "_" + randomSuffix; // 去掉前缀的部分 + user.setNickName(nickName != null ? nickName : ("用户" + displayName)); + + user.setUserType(userType); // "01":兽医, "02":牧户 + user.setEmail(""); + user.setPhonenumber(phone); + user.setSex("0"); + user.setAvatar(avatarUrl != null ? avatarUrl : ""); + + // 设置默认密码(微信登录用不到,但PC端登录需要) + String defaultPassword = configService.selectConfigByKey("sys.user.initPassword"); + user.setPassword(com.chenhai.common.utils.SecurityUtils.encryptPassword(defaultPassword)); + + user.setStatus("0"); // 正常状态 + user.setDelFlag("0"); + user.setCreateTime(new Date()); + + // 如果是兽医,设置初始审核状态 + // if ("01".equals(userType)) { + // user.setVetStatus("0"); // 0:未提交资质, 1:审核中, 2:已认证, 3:审核不通过 + // } + + userService.insertUser(user); + + // 重新查询获取完整用户信息 + return userService.selectUserByUserName(username); + } + + // ==================================================================== + // =================== 多端登录方法结束 =============================== + // ==================================================================== +} \ No newline at end of file diff --git a/chenhai-framework/src/main/java/com/chenhai/framework/web/service/TokenService.java b/chenhai-framework/src/main/java/com/chenhai/framework/web/service/TokenService.java index 80b227c..5061e80 100644 --- a/chenhai-framework/src/main/java/com/chenhai/framework/web/service/TokenService.java +++ b/chenhai-framework/src/main/java/com/chenhai/framework/web/service/TokenService.java @@ -25,7 +25,7 @@ import io.jsonwebtoken.SignatureAlgorithm; /** * token验证处理 - * + * * @author ruoyi */ @Component @@ -45,6 +45,20 @@ public class TokenService @Value("${token.expireTime}") private int expireTime; + // ========== 新增:多端token时长配置 ========== + @Value("${token.expireTime.herdsman-app:43200}") + private int herdsmanAppExpireTime; + + @Value("${token.expireTime.vet-app:10080}") + private int vetAppExpireTime; + + @Value("${token.expireTime.vet-pc:480}") + private int vetPcExpireTime; + + @Value("${token.expireTime.admin:30}") + private int adminExpireTime; + // ============================================ + protected static final long MILLIS_SECOND = 1000; protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; @@ -56,7 +70,7 @@ public class TokenService /** * 获取用户身份信息 - * + * * @return 用户信息 */ public LoginUser getLoginUser(HttpServletRequest request) @@ -107,7 +121,7 @@ public class TokenService /** * 创建令牌 - * + * * @param loginUser 用户信息 * @return 令牌 */ @@ -116,17 +130,31 @@ public class TokenService String token = IdUtils.fastUUID(); loginUser.setToken(token); setUserAgent(loginUser); - refreshToken(loginUser); + + // 关键修复:直接在这里计算过期时间,确保clientType生效 + int customExpireTime = getExpireTimeByClientType(loginUser.getClientType()); + loginUser.setLoginTime(System.currentTimeMillis()); + loginUser.setExpireTime(loginUser.getLoginTime() + customExpireTime * MILLIS_MINUTE); + + // 根据uuid将loginUser缓存 + String userKey = getTokenKey(loginUser.getToken()); + redisCache.setCacheObject(userKey, loginUser, customExpireTime, TimeUnit.MINUTES); Map claims = new HashMap<>(); claims.put(Constants.LOGIN_USER_KEY, token); claims.put(Constants.JWT_USERNAME, loginUser.getUsername()); + + // 可选:在JWT中存储clientType以便解析 + if (loginUser.getClientType() != null) { + claims.put("clientType", loginUser.getClientType()); + } + return createToken(claims); } /** * 验证令牌有效期,相差不足20分钟,自动刷新缓存 - * + * * @param loginUser 登录信息 * @return 令牌 */ @@ -142,19 +170,11 @@ public class TokenService /** * 刷新令牌有效期 - * + * * @param loginUser 登录信息 */ -// public void refreshToken(LoginUser loginUser) -// { -// loginUser.setLoginTime(System.currentTimeMillis()); -// loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); -// // 根据uuid将loginUser缓存 -// String userKey = getTokenKey(loginUser.getToken()); -// redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES); -// } - // 2. 修改refreshToken方法,支持多端 - public void refreshToken(LoginUser loginUser) { + public void refreshToken(LoginUser loginUser) + { loginUser.setLoginTime(System.currentTimeMillis()); // 根据客户端类型设置不同的过期时间 @@ -168,7 +188,7 @@ public class TokenService /** * 设置用户代理信息 - * + * * @param loginUser 登录信息 */ public void setUserAgent(LoginUser loginUser) @@ -244,44 +264,27 @@ public class TokenService /** * 根据客户端类型获取token过期时间(分钟) + * 注意:原有登录逻辑(如/admin登录)没有clientType,会使用默认的expireTime */ private int getExpireTimeByClientType(String clientType) { if (clientType == null) { - return expireTime; // 默认30分钟 + return expireTime; // 默认30分钟,兼容原有登录 } switch(clientType) { case "herdsman-app": - // 从配置读取牧户token时长,默认30天 - return 43200; // 30天(分钟) + // 从配置读取牧户token时长 + return herdsmanAppExpireTime; case "vet-app": - return 10080; // 7天 + return vetAppExpireTime; case "vet-pc": - return 480; // 8小时 + return vetPcExpireTime; case "admin": + // admin后台登录,使用默认或配置 + return adminExpireTime; default: + // 未知类型,使用默认值,确保兼容性 return expireTime; // 30分钟 } } - - // 修改createToken方法,使用客户端类型决定过期时间 -// public String createToken(LoginUser loginUser) { -// String token = IdUtils.fastUUID(); -// loginUser.setToken(token); -// setUserAgent(loginUser); -// -// // 根据客户端类型设置不同的过期时间 -// int customExpireTime = getExpireTimeByClientType(loginUser.getClientType()); -// loginUser.setLoginTime(System.currentTimeMillis()); -// loginUser.setExpireTime(loginUser.getLoginTime() + customExpireTime * MILLIS_MINUTE); -// -// // 根据uuid将loginUser缓存 -// String userKey = getTokenKey(loginUser.getToken()); -// redisCache.setCacheObject(userKey, loginUser, customExpireTime, TimeUnit.MINUTES); -// -// Map claims = new HashMap<>(); -// claims.put(Constants.LOGIN_USER_KEY, token); -// claims.put(Constants.JWT_USERNAME, loginUser.getUsername()); -// return createToken(claims); -// } -} +} \ No newline at end of file