1.优化登录挤下线的逻辑
This commit is contained in:
@@ -1,13 +1,13 @@
|
|||||||
package com.hula.utils;
|
package com.hula.utils;
|
||||||
|
|
||||||
import cn.hutool.extra.spring.SpringUtil;
|
import cn.hutool.extra.spring.SpringUtil;
|
||||||
import com.fasterxml.jackson.core.JsonParser;
|
|
||||||
import com.fasterxml.jackson.core.type.TypeReference;
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.data.redis.connection.RedisConnection;
|
import org.springframework.data.redis.connection.RedisConnection;
|
||||||
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
import org.springframework.data.redis.connection.RedisConnectionFactory;
|
||||||
import org.springframework.data.redis.core.Cursor;
|
import org.springframework.data.redis.core.Cursor;
|
||||||
|
import org.springframework.data.redis.core.RedisCallback;
|
||||||
import org.springframework.data.redis.core.RedisConnectionUtils;
|
import org.springframework.data.redis.core.RedisConnectionUtils;
|
||||||
import org.springframework.data.redis.core.ScanOptions;
|
import org.springframework.data.redis.core.ScanOptions;
|
||||||
import org.springframework.data.redis.core.StringRedisTemplate;
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
@@ -274,7 +274,51 @@ public class RedisUtils {
|
|||||||
return list.stream().map(o -> toBeanOrNull(o, tClass)).collect(Collectors.toList());
|
return list.stream().map(o -> toBeanOrNull(o, tClass)).collect(Collectors.toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
static <T> T toBeanOrNull(String json, Class<T> tClass) {
|
/**
|
||||||
|
* 查询key下面的所有key值
|
||||||
|
* @param keyPattern
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static List<String> multiGet(String keyPattern) {
|
||||||
|
Set<String> keys = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
|
||||||
|
Set<String> result = new HashSet<>();
|
||||||
|
Cursor<byte[]> cursor = connection.scan(ScanOptions.scanOptions().match(keyPattern).count(100).build());
|
||||||
|
while (cursor.hasNext()) {
|
||||||
|
result.add(new String(cursor.next()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
return stringRedisTemplate.opsForValue().multiGet(keys);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 匹配所有key并删除
|
||||||
|
* @param keyPattern
|
||||||
|
*/
|
||||||
|
public static void multiDelete(String keyPattern) {
|
||||||
|
// 1. 使用SCAN获取所有匹配的键
|
||||||
|
Set<String> keys = stringRedisTemplate.execute((RedisCallback<Set<String>>) connection -> {
|
||||||
|
Set<String> result = new HashSet<>();
|
||||||
|
Cursor<byte[]> cursor = connection.scan(
|
||||||
|
ScanOptions.scanOptions()
|
||||||
|
.match(keyPattern)
|
||||||
|
.count(100)
|
||||||
|
.build()
|
||||||
|
);
|
||||||
|
while (cursor.hasNext()) {
|
||||||
|
result.add(new String(cursor.next()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
});
|
||||||
|
|
||||||
|
// 2. 批量删除所有键
|
||||||
|
if (keys != null && !keys.isEmpty()) {
|
||||||
|
stringRedisTemplate.delete(keys);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static <T> T toBeanOrNull(String json, Class<T> tClass) {
|
||||||
return json == null ? null : JsonUtils.toObj(json, tClass);
|
return json == null ? null : JsonUtils.toObj(json, tClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -285,9 +329,7 @@ public class RedisUtils {
|
|||||||
public static <T> void multiSet(Map<String, T> map, long time) {
|
public static <T> void multiSet(Map<String, T> map, long time) {
|
||||||
Map<String, String> collect = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, (e) -> objToStr(e.getValue())));
|
Map<String, String> collect = map.entrySet().stream().collect(Collectors.toMap(Map.Entry::getKey, (e) -> objToStr(e.getValue())));
|
||||||
stringRedisTemplate.opsForValue().multiSet(collect);
|
stringRedisTemplate.opsForValue().multiSet(collect);
|
||||||
map.forEach((key, value) -> {
|
map.forEach((key, value) -> expire(key, time));
|
||||||
expire(key, time);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -108,6 +108,7 @@ public class ChatServiceImpl extends ServiceImpl<ChatMapper, Chat> implements IC
|
|||||||
chat.setUid(command.getUid());
|
chat.setUid(command.getUid());
|
||||||
chat.setCreatedBy(command.getUid());
|
chat.setCreatedBy(command.getUid());
|
||||||
chat.setCreatedTime(LocalDateTime.now());
|
chat.setCreatedTime(LocalDateTime.now());
|
||||||
|
chat.setId(null);
|
||||||
chatMapper.insert(chat);
|
chatMapper.insert(chat);
|
||||||
return ChatVO.builder().chatNumber(chat.getChatNumber()).prompt(command.getPrompt()).build();
|
return ChatVO.builder().chatNumber(chat.getChatNumber()).prompt(command.getPrompt()).build();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,6 +71,11 @@ public class RedisKey {
|
|||||||
*/
|
*/
|
||||||
public static final String GROUP_ANNOUNCEMENTS_FORMAT = "groupInfo:announcements_%d";
|
public static final String GROUP_ANNOUNCEMENTS_FORMAT = "groupInfo:announcements_%d";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户token存放 格式:终端:uid
|
||||||
|
*/
|
||||||
|
public static final String USER_TOKEN_UID_FORMAT = "userToken:%s:uid_%d";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户token存放 格式:终端:uid:uuid
|
* 用户token存放 格式:终端:uid:uuid
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -24,5 +24,5 @@ public class UploadUrlReq extends BaseEntity {
|
|||||||
private String fileName;
|
private String fileName;
|
||||||
@ApiModelProperty(value = "上传场景chat.聊天室,emoji.表情包,avatar.头像")
|
@ApiModelProperty(value = "上传场景chat.聊天室,emoji.表情包,avatar.头像")
|
||||||
@NotNull
|
@NotNull
|
||||||
private Integer scene;
|
private String scene;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.hula.core.user.service.impl;
|
package com.hula.core.user.service.impl;
|
||||||
|
|
||||||
|
import cn.hutool.core.collection.CollUtil;
|
||||||
import cn.hutool.core.lang.UUID;
|
import cn.hutool.core.lang.UUID;
|
||||||
import cn.hutool.core.util.StrUtil;
|
import cn.hutool.core.util.StrUtil;
|
||||||
import com.auth0.jwt.interfaces.Claim;
|
import com.auth0.jwt.interfaces.Claim;
|
||||||
@@ -55,17 +56,17 @@ public class TokenServiceImpl implements TokenService {
|
|||||||
String uuid = UUID.randomUUID().toString(true);
|
String uuid = UUID.randomUUID().toString(true);
|
||||||
String tokenKey = RedisKey.getKey(RedisKey.USER_TOKEN_FORMAT, loginType, uid, uuid);
|
String tokenKey = RedisKey.getKey(RedisKey.USER_TOKEN_FORMAT, loginType, uid, uuid);
|
||||||
String refreshTokenKey = RedisKey.getKey(RedisKey.USER_REFRESH_TOKEN_FORMAT, loginType, uid, uuid);
|
String refreshTokenKey = RedisKey.getKey(RedisKey.USER_REFRESH_TOKEN_FORMAT, loginType, uid, uuid);
|
||||||
String token = RedisUtils.getStr(tokenKey), refreshToken;
|
String key = RedisKey.getKey(RedisKey.USER_REFRESH_TOKEN_UID_FORMAT, loginType, uid) + "*";
|
||||||
String key = RedisKey.getKey(RedisKey.USER_REFRESH_TOKEN_UID_FORMAT, loginType, uid);
|
RedisUtils.multiDelete(RedisKey.getKey(RedisKey.USER_TOKEN_UID_FORMAT, loginType, uid) + "*");
|
||||||
RedisUtils.del(tokenKey, key);
|
|
||||||
|
|
||||||
// 1.2 token存在 旧设备下线
|
// 1.2 token存在 旧设备下线
|
||||||
if (StrUtil.isNotBlank(token)) {
|
if (CollUtil.isNotEmpty(RedisUtils.multiGet(key))) {
|
||||||
|
RedisUtils.multiDelete(key);
|
||||||
applicationEventPublisher.publishEvent(new TokenExpireEvent(this, new OffLineResp(uid, loginType, RequestHolder.get().getIp(), uuid)));
|
applicationEventPublisher.publishEvent(new TokenExpireEvent(this, new OffLineResp(uid, loginType, RequestHolder.get().getIp(), uuid)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. 创建用户token
|
// 2. 创建用户token
|
||||||
token = JwtUtils.createToken(uid, loginType, uuid, TOKEN_EXPIRE_DAYS);
|
String token = JwtUtils.createToken(uid, loginType, uuid, TOKEN_EXPIRE_DAYS), refreshToken;
|
||||||
refreshToken = JwtUtils.createToken(uid, loginType, uuid, TOKEN_RENEWAL_DAYS);
|
refreshToken = JwtUtils.createToken(uid, loginType, uuid, TOKEN_RENEWAL_DAYS);
|
||||||
|
|
||||||
// 3. 刷新存放时间
|
// 3. 刷新存放时间
|
||||||
|
|||||||
Reference in New Issue
Block a user