mirror of
https://github.com/zongzibinbin/MallChat.git
synced 2026-03-14 06:03:42 +08:00
feat:
黑名单
This commit is contained in:
@@ -117,6 +117,7 @@ CREATE TABLE `user` (
|
|||||||
`last_opt_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '最后上下线时间',
|
`last_opt_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '最后上下线时间',
|
||||||
`ip_info` json NULL COMMENT 'ip信息',
|
`ip_info` json NULL COMMENT 'ip信息',
|
||||||
`item_id` bigint(20) NULL DEFAULT NULL COMMENT '佩戴的徽章id',
|
`item_id` bigint(20) NULL DEFAULT NULL COMMENT '佩戴的徽章id',
|
||||||
|
`status` int(11) DEFAULT "0" COMMENT '使用状态 0.正常 1拉黑',
|
||||||
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||||
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
||||||
PRIMARY KEY (`id`) USING BTREE,
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
@@ -158,4 +159,14 @@ CREATE TABLE `wx_msg` (
|
|||||||
INDEX `idx_update_time`(`update_time`) USING BTREE
|
INDEX `idx_update_time`(`update_time`) USING BTREE
|
||||||
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信消息表' ROW_FORMAT = Dynamic;
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '微信消息表' ROW_FORMAT = Dynamic;
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `black`;
|
||||||
|
CREATE TABLE `black` (
|
||||||
|
`id` bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 'id',
|
||||||
|
`type` int(11) NOT NULL COMMENT '拉黑目标类型 1.ip 2uid',
|
||||||
|
`target` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL COMMENT '拉黑目标',
|
||||||
|
`create_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '创建时间',
|
||||||
|
`update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间',
|
||||||
|
PRIMARY KEY (`id`) USING BTREE,
|
||||||
|
UNIQUE INDEX `idx_type_target`(`type`, `target`) USING BTREE
|
||||||
|
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci COMMENT = '黑名单' ROW_FORMAT = Dynamic;
|
||||||
SET FOREIGN_KEY_CHECKS = 1;
|
SET FOREIGN_KEY_CHECKS = 1;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ public class CacheConfig extends CachingConfigurerSupport {
|
|||||||
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
|
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
|
||||||
// 方案一(常用):定制化缓存Cache
|
// 方案一(常用):定制化缓存Cache
|
||||||
cacheManager.setCaffeine(Caffeine.newBuilder()
|
cacheManager.setCaffeine(Caffeine.newBuilder()
|
||||||
.expireAfterWrite(10, TimeUnit.MINUTES)
|
.expireAfterWrite(5, TimeUnit.MINUTES)
|
||||||
.initialCapacity(100)
|
.initialCapacity(100)
|
||||||
.maximumSize(200));
|
.maximumSize(200));
|
||||||
return cacheManager;
|
return cacheManager;
|
||||||
|
|||||||
@@ -81,6 +81,12 @@ public class User implements Serializable {
|
|||||||
@TableField("item_id")
|
@TableField("item_id")
|
||||||
private Long itemId;
|
private Long itemId;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户状态 0正常 1拉黑
|
||||||
|
*/
|
||||||
|
@TableField("status")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 创建时间
|
* 创建时间
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.abin.mallchat.common.user.domain.enums;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description: 物品枚举
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-03-19
|
||||||
|
*/
|
||||||
|
@AllArgsConstructor
|
||||||
|
@Getter
|
||||||
|
public enum BlackTypeEnum {
|
||||||
|
IP(1),
|
||||||
|
UID(2),
|
||||||
|
;
|
||||||
|
|
||||||
|
private final Integer type;
|
||||||
|
|
||||||
|
}
|
||||||
@@ -8,15 +8,20 @@ import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
|||||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||||
import com.abin.mallchat.common.common.utils.CursorUtils;
|
import com.abin.mallchat.common.common.utils.CursorUtils;
|
||||||
import com.abin.mallchat.common.common.utils.RedisUtils;
|
import com.abin.mallchat.common.common.utils.RedisUtils;
|
||||||
|
import com.abin.mallchat.common.user.dao.BlackDao;
|
||||||
import com.abin.mallchat.common.user.dao.UserDao;
|
import com.abin.mallchat.common.user.dao.UserDao;
|
||||||
|
import com.abin.mallchat.common.user.domain.entity.Black;
|
||||||
import com.abin.mallchat.common.user.domain.entity.User;
|
import com.abin.mallchat.common.user.domain.entity.User;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.cache.annotation.Cacheable;
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
import org.springframework.util.CollectionUtils;
|
import org.springframework.util.CollectionUtils;
|
||||||
|
|
||||||
import java.security.PublicKey;
|
import java.security.PublicKey;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.function.Function;
|
import java.util.function.Function;
|
||||||
|
import java.util.stream.Collector;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@@ -32,6 +37,8 @@ public class UserCache {
|
|||||||
private CursorUtils cursorUtils;
|
private CursorUtils cursorUtils;
|
||||||
@Autowired
|
@Autowired
|
||||||
private UserDao userDao;
|
private UserDao userDao;
|
||||||
|
@Autowired
|
||||||
|
private BlackDao blackDao;
|
||||||
|
|
||||||
public Long getOnlineNum() {
|
public Long getOnlineNum() {
|
||||||
String onlineKey = RedisKey.getKey(RedisKey.ONLINE_UID_ZET);
|
String onlineKey = RedisKey.getKey(RedisKey.ONLINE_UID_ZET);
|
||||||
@@ -112,4 +119,17 @@ public class UserCache {
|
|||||||
RedisUtils.del(key);
|
RedisUtils.del(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Cacheable(cacheNames = "user", key = "'blackList'")
|
||||||
|
public Map<Integer, Set<String>> getBlackMap() {
|
||||||
|
Map<Integer, List<Black>> collect = blackDao.list().stream().collect(Collectors.groupingBy(Black::getType));
|
||||||
|
Map<Integer, Set<String>> result =new HashMap<>();
|
||||||
|
for (Map.Entry<Integer, List<Black>> entry : collect.entrySet()) {
|
||||||
|
result.put(entry.getKey(),entry.getValue().stream().map(Black::getTarget).collect(Collectors.toSet()));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@CacheEvict(cacheNames = "user", key = "'blackList'")
|
||||||
|
public Map<Integer, Set<String>> evictBlackMap() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,9 @@ import com.abin.mallchat.common.common.domain.vo.request.CursorPageBaseReq;
|
|||||||
import com.abin.mallchat.common.common.domain.vo.response.ApiResult;
|
import com.abin.mallchat.common.common.domain.vo.response.ApiResult;
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
import com.abin.mallchat.common.common.domain.vo.response.CursorPageBaseResp;
|
||||||
import com.abin.mallchat.common.common.domain.vo.response.IdRespVO;
|
import com.abin.mallchat.common.common.domain.vo.response.IdRespVO;
|
||||||
|
import com.abin.mallchat.common.user.dao.UserDao;
|
||||||
|
import com.abin.mallchat.common.user.domain.enums.BlackTypeEnum;
|
||||||
|
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq;
|
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageMarkReq;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq;
|
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessagePageReq;
|
||||||
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
|
import com.abin.mallchat.custom.chat.domain.vo.request.ChatMessageReq;
|
||||||
@@ -22,6 +25,8 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||||||
import org.springframework.web.bind.annotation.*;
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>
|
* <p>
|
||||||
@@ -37,6 +42,8 @@ import javax.validation.Valid;
|
|||||||
public class ChatController {
|
public class ChatController {
|
||||||
@Autowired
|
@Autowired
|
||||||
private ChatService chatService;
|
private ChatService chatService;
|
||||||
|
@Autowired
|
||||||
|
private UserCache userCache;
|
||||||
|
|
||||||
@GetMapping("/public/room/page")
|
@GetMapping("/public/room/page")
|
||||||
@ApiOperation("会话列表")
|
@ApiOperation("会话列表")
|
||||||
@@ -47,7 +54,16 @@ public class ChatController {
|
|||||||
@GetMapping("/public/member/page")
|
@GetMapping("/public/member/page")
|
||||||
@ApiOperation("群成员列表")
|
@ApiOperation("群成员列表")
|
||||||
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(CursorPageBaseReq request) {
|
public ApiResult<CursorPageBaseResp<ChatMemberResp>> getMemberPage(CursorPageBaseReq request) {
|
||||||
return ApiResult.success(chatService.getMemberPage(request));
|
CursorPageBaseResp<ChatMemberResp> memberPage = chatService.getMemberPage(request);
|
||||||
|
filterBlackMember(memberPage);
|
||||||
|
return ApiResult.success(memberPage);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterBlackMember(CursorPageBaseResp<ChatMemberResp> memberPage) {
|
||||||
|
memberPage.getList().removeIf(a->getBlackUidSet().contains(a.getUid().toString()));
|
||||||
|
}
|
||||||
|
private Set<String> getBlackUidSet(){
|
||||||
|
return userCache.getBlackMap().get(BlackTypeEnum.UID.getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/public/member/statistic")
|
@GetMapping("/public/member/statistic")
|
||||||
@@ -59,9 +75,14 @@ public class ChatController {
|
|||||||
@GetMapping("/public/msg/page")
|
@GetMapping("/public/msg/page")
|
||||||
@ApiOperation("消息列表")
|
@ApiOperation("消息列表")
|
||||||
public ApiResult<CursorPageBaseResp<ChatMessageResp>> getMsgPage(ChatMessagePageReq request) {
|
public ApiResult<CursorPageBaseResp<ChatMessageResp>> getMsgPage(ChatMessagePageReq request) {
|
||||||
return ApiResult.success(chatService.getMsgPage(request, RequestHolder.get().getUid()));
|
CursorPageBaseResp<ChatMessageResp> msgPage = chatService.getMsgPage(request, RequestHolder.get().getUid());
|
||||||
|
filterBlackMsg(msgPage);
|
||||||
|
return ApiResult.success(msgPage);
|
||||||
|
}
|
||||||
|
private void filterBlackMsg(CursorPageBaseResp<ChatMessageResp> memberPage) {
|
||||||
|
memberPage.getList().removeIf(a->getBlackUidSet().contains(a.getFromUser().getUid().toString()));
|
||||||
|
System.out.println(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping("/msg")
|
@PostMapping("/msg")
|
||||||
@ApiOperation("发送消息")
|
@ApiOperation("发送消息")
|
||||||
@FrequencyControl(time = 5, count = 2, target = FrequencyControl.Target.UID)
|
@FrequencyControl(time = 5, count = 2, target = FrequencyControl.Target.UID)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.abin.mallchat.custom.common.config;
|
package com.abin.mallchat.custom.common.config;
|
||||||
|
|
||||||
|
import com.abin.mallchat.custom.common.intecepter.BlackInterceptor;
|
||||||
import com.abin.mallchat.custom.common.intecepter.CollectorInterceptor;
|
import com.abin.mallchat.custom.common.intecepter.CollectorInterceptor;
|
||||||
import com.abin.mallchat.custom.common.intecepter.TokenInterceptor;
|
import com.abin.mallchat.custom.common.intecepter.TokenInterceptor;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
@@ -19,11 +20,15 @@ public class InterceptorConfig implements WebMvcConfigurer {
|
|||||||
private TokenInterceptor tokenInterceptor;
|
private TokenInterceptor tokenInterceptor;
|
||||||
@Autowired
|
@Autowired
|
||||||
private CollectorInterceptor collectorInterceptor;
|
private CollectorInterceptor collectorInterceptor;
|
||||||
|
@Autowired
|
||||||
|
private BlackInterceptor blackInterceptor;
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
registry.addInterceptor(tokenInterceptor)
|
registry.addInterceptor(tokenInterceptor)
|
||||||
.addPathPatterns("/capi/**");
|
.addPathPatterns("/capi/**");
|
||||||
registry.addInterceptor(collectorInterceptor)
|
registry.addInterceptor(collectorInterceptor)
|
||||||
.addPathPatterns("/capi/**");
|
.addPathPatterns("/capi/**");
|
||||||
|
registry.addInterceptor(blackInterceptor)
|
||||||
|
.addPathPatterns("/capi/**");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,56 @@
|
|||||||
|
package com.abin.mallchat.custom.common.intecepter;
|
||||||
|
|
||||||
|
import cn.hutool.extra.servlet.ServletUtil;
|
||||||
|
import com.abin.mallchat.common.common.domain.dto.RequestInfo;
|
||||||
|
import com.abin.mallchat.common.common.exception.HttpErrorEnum;
|
||||||
|
import com.abin.mallchat.common.common.utils.RequestHolder;
|
||||||
|
import com.abin.mallchat.common.user.domain.enums.BlackTypeEnum;
|
||||||
|
import com.abin.mallchat.common.user.service.cache.UserCache;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 黑名单拦截
|
||||||
|
*/
|
||||||
|
@Order(2)
|
||||||
|
@Slf4j
|
||||||
|
@Component
|
||||||
|
public class BlackInterceptor implements HandlerInterceptor{
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserCache userCache;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
Map<Integer, Set<String>> blackMap = userCache.getBlackMap();
|
||||||
|
RequestInfo requestInfo = RequestHolder.get();
|
||||||
|
if(inBlackList(requestInfo.getUid(),blackMap.get(BlackTypeEnum.UID.getType()))){
|
||||||
|
HttpErrorEnum.ACCESS_DENIED.sendHttpError(response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if(inBlackList(requestInfo.getIp(),blackMap.get(BlackTypeEnum.IP.getType()))){
|
||||||
|
HttpErrorEnum.ACCESS_DENIED.sendHttpError(response);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
private boolean inBlackList(Object target, Set<String> blackSet){
|
||||||
|
if(Objects.isNull(target)||Objects.isNull(blackSet)){
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return blackSet.contains(target.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -17,16 +17,10 @@ import java.util.Optional;
|
|||||||
/**
|
/**
|
||||||
* 信息收集的拦截器
|
* 信息收集的拦截器
|
||||||
*/
|
*/
|
||||||
@Order
|
@Order(1)
|
||||||
@Slf4j
|
@Slf4j
|
||||||
@Component
|
@Component
|
||||||
public class CollectorInterceptor implements HandlerInterceptor, WebMvcConfigurer {
|
public class CollectorInterceptor implements HandlerInterceptor{
|
||||||
|
|
||||||
@Override
|
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
|
||||||
registry.addInterceptor(this)
|
|
||||||
.addPathPatterns("/**");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
package com.abin.mallchat.custom.user.domain.enums;
|
package com.abin.mallchat.custom.user.domain.enums;
|
||||||
|
|
||||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSLoginSuccess;
|
import com.abin.mallchat.custom.user.domain.vo.response.ws.*;
|
||||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSLoginUrl;
|
|
||||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSMessage;
|
|
||||||
import com.abin.mallchat.custom.user.domain.vo.response.ws.WSOnlineOfflineNotify;
|
|
||||||
import lombok.AllArgsConstructor;
|
import lombok.AllArgsConstructor;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
|
|
||||||
@@ -26,6 +23,7 @@ public enum WSRespTypeEnum {
|
|||||||
MESSAGE(4, "新消息", WSMessage.class),
|
MESSAGE(4, "新消息", WSMessage.class),
|
||||||
ONLINE_OFFLINE_NOTIFY(5, "上下线通知", WSOnlineOfflineNotify.class),
|
ONLINE_OFFLINE_NOTIFY(5, "上下线通知", WSOnlineOfflineNotify.class),
|
||||||
INVALIDATE_TOKEN(6, "使前端的token失效,意味着前端需要重新登录", null),
|
INVALIDATE_TOKEN(6, "使前端的token失效,意味着前端需要重新登录", null),
|
||||||
|
BLACK(7, "拉黑用户", WSBlack.class),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final Integer type;
|
private final Integer type;
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
package com.abin.mallchat.custom.user.domain.vo.response.ws;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Builder;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.NoArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Description:
|
||||||
|
* Author: <a href="https://github.com/zongzibinbin">abin</a>
|
||||||
|
* Date: 2023-03-19
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Builder
|
||||||
|
@AllArgsConstructor
|
||||||
|
@NoArgsConstructor
|
||||||
|
public class WSBlack {
|
||||||
|
private Long uid;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user