fix: 修复token续命bug

This commit is contained in:
fit2cloud-chenyw 2021-03-10 11:49:18 +08:00
parent fec733f262
commit 2a766461ca
7 changed files with 80 additions and 14 deletions

View File

@ -13,8 +13,9 @@ import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Set;
import java.util.stream.Collectors;
@ -23,7 +24,8 @@ import java.util.stream.Collectors;
@Component
public class F2CRealm extends AuthorizingRealm {
@Resource
@Autowired
@Lazy //shiro组件加载过早 让authUserService等一等再注入 否则 注入的可能不是代理对象
private AuthUserService authUserService;
@ -36,7 +38,6 @@ public class F2CRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
Long userId = JWTUtils.tokenInfoByToken(principals.toString()).getUserId();
//SysUserEntity user = authUserService.getUserById(userId);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
Set<String> role = authUserService.roles(userId).stream().collect(Collectors.toSet());
simpleAuthorizationInfo.addRoles(role);

View File

@ -45,8 +45,8 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
HttpServletRequest httpServletRequest = (HttpServletRequest) request;
String authorization = httpServletRequest.getHeader("Authorization");
if (JWTUtils.needRefresh(authorization)){
// 当没有出现登录超时 且需要刷新token 则执行刷新token
if (!JWTUtils.loginExpire(authorization) && JWTUtils.needRefresh(authorization)){
authorization = refreshToken(request, response);
}
JWTToken token = new JWTToken(authorization);
@ -81,7 +81,13 @@ public class JWTFilter extends BasicHttpAuthenticationFilter {
AuthUserService authUserService = CommonBeanFactory.getBean(AuthUserService.class);
SysUserEntity user = authUserService.getUserById(tokenInfo.getUserId());
String password = user.getPassword();
// 删除老token操作时间
JWTUtils.removeTokenExpire(token);
String newToken = JWTUtils.sign(tokenInfo, password);
// 记录新token操作时间
JWTUtils.addTokenExpire(newToken);
JWTToken jwtToken = new JWTToken(newToken);
this.getSubject(request, response).login(jwtToken);
// 设置响应的Header头新Token

View File

@ -49,6 +49,8 @@ public class AuthServer implements AuthApi {
Map<String,Object> result = new HashMap<>();
TokenInfo tokenInfo = TokenInfo.builder().userId(user.getUserId()).username(username).lastLoginTime(System.currentTimeMillis()).build();
String token = JWTUtils.sign(tokenInfo, realPwd);
// 记录token操作时间
JWTUtils.addTokenExpire(token);
result.put("token", token);
ServletUtils.setToken(token);
return result;
@ -79,6 +81,9 @@ public class AuthServer implements AuthApi {
@Override
public String test() {
SysUserEntity userById = authUserService.getUserById(4L);
String nickName = userById.getNickName();
System.out.println(nickName);
return "apple";
}
}

View File

@ -35,6 +35,7 @@ public class ShiroServiceImpl implements ShiroService {
// filterChainDefinitionMap.put("/404", "anon");
// 登陆
// filterChainDefinitionMap.put("/api/auth/logout", "anon");
filterChainDefinitionMap.put("/api/auth/test", "anon");
filterChainDefinitionMap.put("/api/auth/login", "anon");
// 退出

View File

@ -6,9 +6,12 @@ import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import io.dataease.auth.entity.TokenInfo;
import io.dataease.commons.utils.CommonBeanFactory;
import io.dataease.commons.utils.ServletUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.CacheManager;
import javax.servlet.http.HttpServletResponse;
import java.util.Date;
@ -19,7 +22,7 @@ public class JWTUtils {
// token过期时间5min (过期会自动刷新续命 目的是避免一直都是同一个token )
private static final long EXPIRE_TIME = 1*60*1000;
// 登录间隔时间10min 超过这个时间强制重新登录
private static final long Login_Interval = 10*60*1000;
private static final long Login_Interval = 2*60*1000;
/**
@ -36,9 +39,10 @@ public class JWTUtils {
.withClaim("userId", tokenInfo.getUserId())
.build();
DecodedJWT jwt = verifier.verify(token);
Long lastLoginTime = jwt.getClaim("lastLoginTime").asLong();
//Long lastLoginTime = jwt.getClaim("lastLoginTime").asLong();
Long lastOperateTime = tokenLastOperateTime(token);
long now = System.currentTimeMillis();
if (now - lastLoginTime > Login_Interval){
if (now - lastOperateTime > Login_Interval){
// 登录超时
HttpServletResponse response = ServletUtils.response();
response.addHeader("Access-Control-Expose-Headers", "authentication-status");
@ -74,6 +78,17 @@ public class JWTUtils {
return new Date().getTime() >= exp.getTime();
}
/**
* 当前token是否登录超时
* @param token
* @return
*/
public static boolean loginExpire(String token){
Long now = System.currentTimeMillis();
Long lastOperateTime = tokenLastOperateTime(token);
return now - lastOperateTime > Login_Interval;
}
public static Date getExp(String token) {
try {
DecodedJWT jwt = JWT.decode(token);
@ -106,4 +121,28 @@ public class JWTUtils {
return null;
}
}
/**
* 获取当前token上次操作时间
* @param token
* @return
*/
public static Long tokenLastOperateTime(String token){
CacheManager cacheManager = CommonBeanFactory.getBean(CacheManager.class);
Cache tokens_expire = cacheManager.getCache("tokens_expire");
Long expTime = tokens_expire.get(token, Long.class);
return expTime;
}
public static void removeTokenExpire(String token){
CacheManager cacheManager = CommonBeanFactory.getBean(CacheManager.class);
Cache tokens_expire = cacheManager.getCache("tokens_expire");
tokens_expire.evict(token);
}
public static void addTokenExpire(String token){
CacheManager cacheManager = CommonBeanFactory.getBean(CacheManager.class);
Cache tokens_expire = cacheManager.getCache("tokens_expire");
tokens_expire.put(token, System.currentTimeMillis());
}
}

View File

@ -111,6 +111,7 @@ public class SysUserService {
return sysUserMapper.updateByPrimaryKeySelective(sysUser);
}
@CacheEvict(value = USER_CACHE_NAME, key = "'user' + #request.userId")
public int adminUpdatePwd(SysUserPwdRequest request){
SysUser sysUser = new SysUser();
sysUser.setUserId(request.getUserId());

View File

@ -7,10 +7,10 @@
user.dir - 用户当前工作目录
java.io.tmpdir - 默认临时文件路径
-->
<!-- <diskStore path="D:/home/Tmp_Ehcache"/>-->
<diskStore path="/opt/dataease/data/ehcache"/>
<!--
name:缓存名称。
maxElementsInMemory:缓存最大数目
maxElementsInMemory:jvm缓存最大数目
maxElementsOnDisk硬盘最大缓存个数。
eternal:对象是否永久有效一但设置了timeout将不起作用。
overflowToDisk:是否保存到磁盘,当系统宕机时
@ -39,10 +39,23 @@
name="users_info"
eternal="false"
maxElementsInMemory="100"
overflowToDisk="false"
diskPersistent="false"
timeToIdleSeconds="0"
timeToLiveSeconds="300"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>
<cache
name="tokens_expire"
eternal="false"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
overflowToDisk="true"
diskPersistent="true"
timeToIdleSeconds="1800"
timeToLiveSeconds="3600"
memoryStoreEvictionPolicy="LRU"
/>