diff --git a/docs/mallchat.sql b/docs/mallchat.sql index f95dcaf..266c79b 100644 --- a/docs/mallchat.sql +++ b/docs/mallchat.sql @@ -117,6 +117,7 @@ CREATE TABLE `user` ( `last_opt_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) COMMENT '最后上下线时间', `ip_info` json NULL COMMENT 'ip信息', `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 '创建时间', `update_time` datetime(3) NOT NULL DEFAULT CURRENT_TIMESTAMP(3) ON UPDATE CURRENT_TIMESTAMP(3) COMMENT '修改时间', PRIMARY KEY (`id`) USING BTREE, @@ -158,4 +159,14 @@ CREATE TABLE `wx_msg` ( INDEX `idx_update_time`(`update_time`) USING BTREE ) 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; diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/common/config/CacheConfig.java b/mallchat-common/src/main/java/com/abin/mallchat/common/common/config/CacheConfig.java index 1a7aec5..dab2d4e 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/common/config/CacheConfig.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/common/config/CacheConfig.java @@ -21,7 +21,7 @@ public class CacheConfig extends CachingConfigurerSupport { CaffeineCacheManager cacheManager = new CaffeineCacheManager(); // 方案一(常用):定制化缓存Cache cacheManager.setCaffeine(Caffeine.newBuilder() - .expireAfterWrite(10, TimeUnit.MINUTES) + .expireAfterWrite(5, TimeUnit.MINUTES) .initialCapacity(100) .maximumSize(200)); return cacheManager; diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/User.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/User.java index 5a63304..e4f4993 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/User.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/entity/User.java @@ -81,6 +81,12 @@ public class User implements Serializable { @TableField("item_id") private Long itemId; + /** + * 用户状态 0正常 1拉黑 + */ + @TableField("status") + private Integer status; + /** * 创建时间 */ diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/BlackTypeEnum.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/BlackTypeEnum.java new file mode 100644 index 0000000..23e9969 --- /dev/null +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/domain/enums/BlackTypeEnum.java @@ -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: abin + * Date: 2023-03-19 + */ +@AllArgsConstructor +@Getter +public enum BlackTypeEnum { + IP(1), + UID(2), + ; + + private final Integer type; + +} diff --git a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java index 6929a4e..940f3d8 100644 --- a/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java +++ b/mallchat-common/src/main/java/com/abin/mallchat/common/user/service/cache/UserCache.java @@ -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.utils.CursorUtils; 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.domain.entity.Black; import com.abin.mallchat.common.user.domain.entity.User; 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.util.CollectionUtils; import java.security.PublicKey; import java.util.*; import java.util.function.Function; +import java.util.stream.Collector; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -32,6 +37,8 @@ public class UserCache { private CursorUtils cursorUtils; @Autowired private UserDao userDao; + @Autowired + private BlackDao blackDao; public Long getOnlineNum() { String onlineKey = RedisKey.getKey(RedisKey.ONLINE_UID_ZET); @@ -112,4 +119,17 @@ public class UserCache { RedisUtils.del(key); } + @Cacheable(cacheNames = "user", key = "'blackList'") + public Map> getBlackMap() { + Map> collect = blackDao.list().stream().collect(Collectors.groupingBy(Black::getType)); + Map> result =new HashMap<>(); + for (Map.Entry> 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> evictBlackMap() { + return null; + } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java index 86412cf..d23af39 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/chat/controller/ChatController.java @@ -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.CursorPageBaseResp; 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.ChatMessagePageReq; 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 javax.validation.Valid; +import java.util.Map; +import java.util.Set; /** *

@@ -37,6 +42,8 @@ import javax.validation.Valid; public class ChatController { @Autowired private ChatService chatService; + @Autowired + private UserCache userCache; @GetMapping("/public/room/page") @ApiOperation("会话列表") @@ -47,7 +54,16 @@ public class ChatController { @GetMapping("/public/member/page") @ApiOperation("群成员列表") public ApiResult> getMemberPage(CursorPageBaseReq request) { - return ApiResult.success(chatService.getMemberPage(request)); + CursorPageBaseResp memberPage = chatService.getMemberPage(request); + filterBlackMember(memberPage); + return ApiResult.success(memberPage); + } + + private void filterBlackMember(CursorPageBaseResp memberPage) { + memberPage.getList().removeIf(a->getBlackUidSet().contains(a.getUid().toString())); + } + private Set getBlackUidSet(){ + return userCache.getBlackMap().get(BlackTypeEnum.UID.getType()); } @GetMapping("/public/member/statistic") @@ -59,9 +75,14 @@ public class ChatController { @GetMapping("/public/msg/page") @ApiOperation("消息列表") public ApiResult> getMsgPage(ChatMessagePageReq request) { - return ApiResult.success(chatService.getMsgPage(request, RequestHolder.get().getUid())); + CursorPageBaseResp msgPage = chatService.getMsgPage(request, RequestHolder.get().getUid()); + filterBlackMsg(msgPage); + return ApiResult.success(msgPage); + } + private void filterBlackMsg(CursorPageBaseResp memberPage) { + memberPage.getList().removeIf(a->getBlackUidSet().contains(a.getFromUser().getUid().toString())); + System.out.println(1); } - @PostMapping("/msg") @ApiOperation("发送消息") @FrequencyControl(time = 5, count = 2, target = FrequencyControl.Target.UID) diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/config/InterceptorConfig.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/config/InterceptorConfig.java index 09bf88e..ad55fbe 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/config/InterceptorConfig.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/config/InterceptorConfig.java @@ -1,5 +1,6 @@ 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.TokenInterceptor; import org.springframework.beans.factory.annotation.Autowired; @@ -19,11 +20,15 @@ public class InterceptorConfig implements WebMvcConfigurer { private TokenInterceptor tokenInterceptor; @Autowired private CollectorInterceptor collectorInterceptor; + @Autowired + private BlackInterceptor blackInterceptor; @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(tokenInterceptor) .addPathPatterns("/capi/**"); registry.addInterceptor(collectorInterceptor) .addPathPatterns("/capi/**"); + registry.addInterceptor(blackInterceptor) + .addPathPatterns("/capi/**"); } } diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/intecepter/BlackInterceptor.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/intecepter/BlackInterceptor.java new file mode 100644 index 0000000..bc2b704 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/intecepter/BlackInterceptor.java @@ -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> 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 blackSet){ + if(Objects.isNull(target)||Objects.isNull(blackSet)){ + return false; + } + return blackSet.contains(target.toString()); + } + +} \ No newline at end of file diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/intecepter/CollectorInterceptor.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/intecepter/CollectorInterceptor.java index c81294a..2fb8d6e 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/intecepter/CollectorInterceptor.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/common/intecepter/CollectorInterceptor.java @@ -17,16 +17,10 @@ import java.util.Optional; /** * 信息收集的拦截器 */ -@Order +@Order(1) @Slf4j @Component -public class CollectorInterceptor implements HandlerInterceptor, WebMvcConfigurer { - - @Override - public void addInterceptors(InterceptorRegistry registry) { - registry.addInterceptor(this) - .addPathPatterns("/**"); - } +public class CollectorInterceptor implements HandlerInterceptor{ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSRespTypeEnum.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSRespTypeEnum.java index 6fa7453..c0d0f2a 100644 --- a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSRespTypeEnum.java +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/enums/WSRespTypeEnum.java @@ -1,9 +1,6 @@ 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.WSLoginUrl; -import com.abin.mallchat.custom.user.domain.vo.response.ws.WSMessage; -import com.abin.mallchat.custom.user.domain.vo.response.ws.WSOnlineOfflineNotify; +import com.abin.mallchat.custom.user.domain.vo.response.ws.*; import lombok.AllArgsConstructor; import lombok.Getter; @@ -26,6 +23,7 @@ public enum WSRespTypeEnum { MESSAGE(4, "新消息", WSMessage.class), ONLINE_OFFLINE_NOTIFY(5, "上下线通知", WSOnlineOfflineNotify.class), INVALIDATE_TOKEN(6, "使前端的token失效,意味着前端需要重新登录", null), + BLACK(7, "拉黑用户", WSBlack.class), ; private final Integer type; diff --git a/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSBlack.java b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSBlack.java new file mode 100644 index 0000000..8619c01 --- /dev/null +++ b/mallchat-custom-server/src/main/java/com/abin/mallchat/custom/user/domain/vo/response/ws/WSBlack.java @@ -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: abin + * Date: 2023-03-19 + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +public class WSBlack { + private Long uid; +}