From 0bf868d3cdf9226e178c076d3b588ed5207409a0 Mon Sep 17 00:00:00 2001 From: kongzy <kongzy> Date: 星期五, 24 十一月 2023 17:51:40 +0800 Subject: [PATCH] merge --- assess-framework/src/main/java/com/gkhy/assess/framework/shiro/service/SysLoginService.java | 99 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 files changed, 99 insertions(+), 0 deletions(-) diff --git a/assess-framework/src/main/java/com/gkhy/assess/framework/shiro/service/SysLoginService.java b/assess-framework/src/main/java/com/gkhy/assess/framework/shiro/service/SysLoginService.java new file mode 100644 index 0000000..a6676c0 --- /dev/null +++ b/assess-framework/src/main/java/com/gkhy/assess/framework/shiro/service/SysLoginService.java @@ -0,0 +1,99 @@ +package com.gkhy.assess.framework.shiro.service; + +import com.gkhy.assess.common.constant.CacheConstant; +import com.gkhy.assess.common.enums.UserStatusEnum; +import com.gkhy.assess.common.exception.ApiException; +import com.gkhy.assess.common.utils.JwtTokenUtil; +import com.gkhy.assess.common.utils.RedisUtils; +import com.gkhy.assess.system.domain.SysUser; +import com.gkhy.assess.system.service.SysUserService; +import com.gkhy.assess.system.utils.ShiroUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.shiro.authc.AuthenticationException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.time.LocalDateTime; + +@Component +public class SysLoginService { + @Autowired + private SysUserService sysUserService; + @Autowired + private SysPasswordService passwordService; + @Autowired + private RedisUtils redisUtils; + + public SysUser login(String username, String password) { + SysUser sysUser=sysUserService.getUserByUsernamePhone(username); + validUser(sysUser); + passwordService.validate(sysUser,password); + recordLoginInfo(sysUser.getId()); + return sysUser; + } + + public void validUser(SysUser sysUser){ + if(sysUser==null) { + throw new ApiException("用户不存在"); + } + if(UserStatusEnum.DELETED.getCode().equals(sysUser.getDelFlag())){ + throw new ApiException("用户已被删除"); + } + if(UserStatusEnum.DISABLE.getCode().equals(sysUser.getStatus())){ + throw new ApiException("用户已被停用"); + } + } + + public SysUser validJwtToken(String jwtToken){ + String username= JwtTokenUtil.getUsername(jwtToken); + if(StringUtils.isEmpty(username)){ + throw new AuthenticationException("token非法无效!"); + } + SysUser sysUser=sysUserService.getUserByUsernamePhone(username); + validUser(sysUser); + if(!jwtTokenRefresh(jwtToken,username,sysUser.getPassword())){ + throw new AuthenticationException("Token失效,请重新登录!"); + } + // setRolePermission(sysUser); + return sysUser; + } + + /** + * JWTToken刷新生命周期 (实现: 用户在线操作不掉线功能) + * 1、登录成功后将用户的JWT生成的Token作为k、v存储到cache缓存里面(这时候k、v值一样),缓存有效期设置为Jwt有效时间的2倍 + * 2、当该用户再次请求时,通过JWTFilter层层校验之后会进入到doGetAuthenticationInfo进行身份验证 + * 3、当该用户这次请求jwt生成的token值已经超时,但该token对应cache中的k还是存在,则表示该用户一直在操作只是JWT的token失效了,程序会给token对应的k映射的v值重新生成JWTToken并覆盖v值,该缓存生命周期重新计算 + * 4、当该用户这次请求jwt在生成的token值已经超时,并在cache中不存在对应的k,则表示该用户账户空闲超时,返回用户信息已失效,请重新登录。 + * 注意: 前端请求Header中设置Authorization保持不变,校验有效性以缓存中的token为准。 + * 用户过期时间 = Jwt有效时间 * 2。 + * + * @param username + * @param passWord + * @return + */ + public boolean jwtTokenRefresh(String jwtToken,String username,String passWord){ + String key=redisUtils.generateKey(CacheConstant.SYS_USER_TOKEN+":"+JwtTokenUtil.md5Encode(jwtToken)); + String cacheToken= (String) redisUtils.get(key); + if(StringUtils.isNotEmpty(cacheToken)){ + // 校验token有效性 + if(!JwtTokenUtil.verify(cacheToken,username,passWord)){ + String newToken=JwtTokenUtil.sign(username,passWord); + // 设置超时时间 + redisUtils.set(key,newToken); + redisUtils.expire(key,JwtTokenUtil.EXPIRATION*2/1000); + } + return true; + } + return false; + } + + + public void recordLoginInfo(Long userId){ + SysUser user=new SysUser(); + user.setId(userId); + user.setLoginIp(ShiroUtils.getIp()); + user.setLoginDate(LocalDateTime.now()); + sysUserService.updateById(user); + + } +} -- Gitblit v1.9.2