Skip to content

Commit 671dc72

Browse files
committed
fix(customer): bad comment interceptor
1 parent 14087e6 commit 671dc72

6 files changed

Lines changed: 73 additions & 34 deletions

File tree

blog-common/src/main/java/com/hackyle/blog/common/constant/CacheKeyConstants.java

Lines changed: 0 additions & 26 deletions
This file was deleted.

blog-customer/src/main/java/com/hackyle/blog/customer/handler/GlobalExceptionHandler.java

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,27 @@
11
package com.hackyle.blog.customer.handler;
22

3+
import com.hackyle.blog.common.domain.ApiResponse;
4+
import com.hackyle.blog.common.exception.BizException;
35
import com.hackyle.blog.common.exception.Page404Exception;
46
import lombok.extern.slf4j.Slf4j;
7+
import org.springframework.core.annotation.Order;
58
import org.springframework.http.HttpStatus;
69
import org.springframework.web.bind.annotation.ControllerAdvice;
710
import org.springframework.web.bind.annotation.ExceptionHandler;
11+
import org.springframework.web.bind.annotation.ResponseBody;
12+
import org.springframework.web.bind.annotation.ResponseStatus;
13+
import org.springframework.web.bind.annotation.RestControllerAdvice;
814
import org.springframework.web.servlet.ModelAndView;
915

1016
import javax.servlet.http.HttpServletRequest;
1117

1218
/**
1319
* 全局异常处理器
14-
* ControllerAdvice表示这是一个控制器增强类,当控制器发生异常且符合类中定义的拦截异常类,将会被拦截。
20+
* ControllerAdvice、RestControllerAdvice表示这是一个控制器增强类,当控制器发生异常且符合类中定义的拦截异常类,将会被拦截。
1521
* 在捕获异常时是按照异常方法的顺序依次捕获(类似于catch关键字后的捕获顺序),所以需要将顶级的异常放在最后
16-
* 注意:各个异常处理方法要同名,采取重载的形式
22+
* 注意:
23+
* RestControllerAdvice修饰的类,并不一定捕获@RestController修饰的controller类抛出的异常
24+
* ControllerAdvice修饰的类,并不一定捕获@Controller修饰的controller类抛出的异常。
1725
*
1826
* 需要跳转到页面的异常
1927
* Page404Exception:跳转到404页面
@@ -28,8 +36,18 @@
2836
* Exception、Error:500
2937
*/
3038
@ControllerAdvice
39+
@RestControllerAdvice
3140
@Slf4j
3241
public class GlobalExceptionHandler {
42+
43+
//@ResponseStatus(HttpStatus.UNPROCESSABLE_ENTITY)
44+
@ResponseBody
45+
@ExceptionHandler(BizException.class)
46+
public ApiResponse<Exception> bizExceptionHandler(HttpServletRequest request, BizException exception) {
47+
log.error("出现BizException异常:", exception);
48+
return ApiResponse.fail(HttpStatus.UNPROCESSABLE_ENTITY.value(), exception.getMessage());
49+
}
50+
3351
//@ResponseStatus(HttpStatus.NOT_FOUND)
3452
@ExceptionHandler(value = Page404Exception.class)
3553
public ModelAndView page404ExceptionHandler(HttpServletRequest request, Page404Exception exception) {
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.hackyle.blog.customer.infrastructure.redis;
2+
3+
/**
4+
* 定义本模块下所有的缓存key前缀
5+
*/
6+
public class CacheKey {
7+
//统一前缀:blog customer
8+
public static final String PREFIX = "bc:";
9+
10+
}

blog-customer/src/main/java/com/hackyle/blog/customer/module/article/controller/CommentController.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import com.hackyle.blog.customer.module.article.service.CommentService;
88
import lombok.extern.slf4j.Slf4j;
99
import org.springframework.beans.factory.annotation.Autowired;
10+
import org.springframework.validation.annotation.Validated;
1011
import org.springframework.web.bind.annotation.GetMapping;
1112
import org.springframework.web.bind.annotation.PostMapping;
1213
import org.springframework.web.bind.annotation.RequestMapping;
@@ -27,7 +28,7 @@ public class CommentController {
2728
* 新增文章评论
2829
*/
2930
@PostMapping
30-
public ApiResponse<String> add(CommentAddDto commentAddDto, HttpServletRequest request) {
31+
public ApiResponse<String> add(@Validated CommentAddDto commentAddDto, HttpServletRequest request) {
3132
log.info("新增文章评论-Controller层入参-commentAddDto={}", JSON.toJSONString(commentAddDto));
3233

3334
boolean commented = commentService.add(commentAddDto);

blog-customer/src/main/java/com/hackyle/blog/customer/module/article/service/impl/CommentServiceImpl.java

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
import com.hackyle.blog.common.enums.DeletedEnum;
66
import com.hackyle.blog.common.enums.StatusEnum;
77
import com.hackyle.blog.common.exception.BizException;
8+
import com.hackyle.blog.common.ip.IpUtils;
89
import com.hackyle.blog.common.util.BeanCopyUtils;
910
import com.hackyle.blog.common.util.SnowFlakeIdUtils;
11+
import com.hackyle.blog.customer.infrastructure.redis.CacheKey;
1012
import com.hackyle.blog.customer.module.article.mapper.ArticleMapper;
1113
import com.hackyle.blog.customer.module.article.mapper.CommentMapper;
1214
import com.hackyle.blog.customer.module.article.model.dto.CommentAddDto;
@@ -15,6 +17,7 @@
1517
import com.hackyle.blog.customer.module.article.model.vo.CommentVo;
1618
import com.hackyle.blog.customer.module.article.service.CommentService;
1719
import lombok.extern.slf4j.Slf4j;
20+
import org.apache.commons.lang3.StringUtils;
1821
import org.springframework.beans.factory.annotation.Autowired;
1922
import org.springframework.data.redis.core.ValueOperations;
2023
import org.springframework.stereotype.Service;
@@ -25,6 +28,7 @@
2528
import java.util.Comparator;
2629
import java.util.List;
2730
import java.util.Map;
31+
import java.util.concurrent.TimeUnit;
2832
import java.util.stream.Collectors;
2933

3034
@Slf4j
@@ -41,10 +45,8 @@ public class CommentServiceImpl extends ServiceImpl<CommentMapper, CommentEntity
4145

4246
@Override
4347
public boolean add(CommentAddDto addDto) {
44-
//恶意提交判定:对某一IP,6小时内对某target限制提交3次,对某父评论限制提交5次
45-
//if(badRequest(request, commentAddDto)) {
46-
// return ApiResponse.fail(ResponseEnum.FRONT_END_ERROR.getCode(), ResponseEnum.FRONT_END_ERROR.getMessage(), "恶意请求,请稍后重试!");
47-
//}
48+
//恶意提交判定
49+
badRequestCheck(addDto);
4850

4951
//检查被评论的文章是否存在
5052
ArticleEntity articleEntity = articleMapper.selectById(addDto.getArticleId());
@@ -71,6 +73,40 @@ public boolean add(CommentAddDto addDto) {
7173
return true;
7274
}
7375

76+
77+
private void badRequestCheck(CommentAddDto commentAddDto) {
78+
String publicIp = IpUtils.getPublicIp(); //注意,这里可能获取到的ip是unknown
79+
//5小时内对某article限制提交5次
80+
String articleIpKey = CacheKey.PREFIX + commentAddDto.getArticleId() + ":" +publicIp;
81+
String articleIpVal = valueOperations.get(articleIpKey);
82+
if(StringUtils.isBlank(articleIpVal)) {
83+
valueOperations.set(articleIpKey, "1", 5, TimeUnit.HOURS);
84+
} else {
85+
int articleIpInt = Integer.parseInt(articleIpVal);
86+
if(articleIpInt > 5) {
87+
log.info("对文章的恶意评论-articleIpKey={},articleIpVal={}", articleIpKey, articleIpVal);
88+
throw new BizException("您对该文章的评论过于频繁,请稍后再试!");
89+
}
90+
valueOperations.increment(articleIpKey, 1);
91+
}
92+
93+
//5小时内对某父评论限制提交5次
94+
if(commentAddDto.getPid() != null) {
95+
String pidIpKey = CacheKey.PREFIX + commentAddDto.getPid() + ":" +publicIp;
96+
String pidIpVal = valueOperations.get(pidIpKey);
97+
if(StringUtils.isBlank(pidIpVal)) {
98+
valueOperations.set(pidIpKey, "1", 5, TimeUnit.HOURS);
99+
} else {
100+
int reqValInt = Integer.parseInt(pidIpVal);
101+
if(reqValInt > 5) {
102+
log.info("对父评论的恶意评论-pidIpKey={},pidIpVal={}", pidIpKey, pidIpVal);
103+
throw new BizException("您对该评论的评论过于频繁,请稍后再试!");
104+
}
105+
valueOperations.increment(pidIpKey, 1);
106+
}
107+
}
108+
}
109+
74110
/**
75111
* 获取文章的顶级评论
76112
* @param articleId 文章id

blog-customer/src/main/resources/static/js/article.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ function postComment(name, email, link, content, rootId, pid) {
116116
tinyMCE.get('commentTextarea').setContent('');
117117
alert("提交成功,请等待管理员审核通过后呈现!")
118118
} else {
119-
alert("提交失败,请重试!")
119+
alert(resp.msg)
120120
}
121121
}, 'json')
122122
}

0 commit comments

Comments
 (0)