6 changed files with 194 additions and 8 deletions
-
4chenhai-admin/src/main/java/com/chenhai/web/controller/system/SysSlaughterInfoController.java
-
5chenhai-common/pom.xml
-
17chenhai-common/src/main/java/com/chenhai/common/annotation/SensitiveCheck.java
-
5chenhai-framework/pom.xml
-
165chenhai-framework/src/main/java/com/chenhai/framework/aspectj/SensitiveCheckAspect.java
-
6chenhai-ui/src/views/system/slaughterInfo/index.vue
@ -0,0 +1,17 @@ |
|||
package com.chenhai.common.annotation; |
|||
|
|||
import java.lang.annotation.*; |
|||
|
|||
/** |
|||
* 敏感词校验注解 |
|||
* 加在Controller方法上,自动检查请求体中的敏感词 |
|||
*/ |
|||
@Target(ElementType.METHOD) |
|||
@Retention(RetentionPolicy.RUNTIME) |
|||
@Documented |
|||
public @interface SensitiveCheck { |
|||
/** |
|||
* 是否抛出异常(默认false,直接返回错误响应) |
|||
*/ |
|||
boolean throwException() default false; |
|||
} |
|||
@ -0,0 +1,165 @@ |
|||
package com.chenhai.framework.aspectj; |
|||
|
|||
import com.chenhai.common.annotation.SensitiveCheck; |
|||
import com.chenhai.common.core.domain.AjaxResult; |
|||
import com.chenhai.common.exception.ServiceException; |
|||
import com.chenhai.common.utils.StringUtils; |
|||
import com.github.houbb.sensitive.word.core.SensitiveWordHelper; |
|||
import org.aspectj.lang.ProceedingJoinPoint; |
|||
import org.aspectj.lang.annotation.Around; |
|||
import org.aspectj.lang.annotation.Aspect; |
|||
import org.springframework.aop.aspectj.MethodInvocationProceedingJoinPoint; |
|||
import org.springframework.aop.framework.ReflectiveMethodInvocation; |
|||
import org.springframework.stereotype.Component; |
|||
|
|||
import java.lang.reflect.Field; |
|||
import java.lang.reflect.Modifier; |
|||
import java.time.LocalDate; |
|||
import java.time.LocalDateTime; |
|||
import java.util.*; |
|||
|
|||
@Aspect |
|||
@Component |
|||
public class SensitiveCheckAspect { |
|||
|
|||
@Around("@annotation(sensitiveCheck)") |
|||
public Object checkSensitiveWords(ProceedingJoinPoint joinPoint, SensitiveCheck sensitiveCheck) throws Throwable { |
|||
// 1. 收集所有敏感词 |
|||
Set<String> allSensitiveWords = new HashSet<>(); |
|||
|
|||
Object[] args = joinPoint.getArgs(); |
|||
if (args != null) { |
|||
for (Object arg : args) { |
|||
if (arg != null) { |
|||
collectSensitiveWords(arg, allSensitiveWords); |
|||
} |
|||
} |
|||
} |
|||
|
|||
// 2. 如果有敏感词,直接返回 |
|||
if (!allSensitiveWords.isEmpty()) { |
|||
return handleResult(allSensitiveWords, sensitiveCheck); |
|||
} |
|||
|
|||
// 3. 没有敏感词,继续执行 |
|||
return joinPoint.proceed(); |
|||
} |
|||
|
|||
/** |
|||
* 递归收集敏感词 |
|||
*/ |
|||
private void collectSensitiveWords(Object obj, Set<String> sensitiveWords) { |
|||
if (obj == null) return; |
|||
|
|||
if (obj instanceof String) { |
|||
// 检查字符串 |
|||
String text = (String) obj; |
|||
if (StringUtils.isNotBlank(text)) { |
|||
sensitiveWords.addAll(SensitiveWordHelper.findAll(text)); |
|||
} |
|||
return; |
|||
} |
|||
|
|||
if (obj instanceof Collection) { |
|||
// 检查集合 |
|||
for (Object item : (Collection<?>) obj) { |
|||
collectSensitiveWords(item, sensitiveWords); |
|||
} |
|||
} |
|||
else if (obj instanceof Map) { |
|||
// 检查Map |
|||
for (Object value : ((Map<?, ?>) obj).values()) { |
|||
collectSensitiveWords(value, sensitiveWords); |
|||
} |
|||
} |
|||
else if (obj.getClass().isArray()) { |
|||
// 检查数组 |
|||
if (!obj.getClass().getComponentType().isPrimitive()) { |
|||
for (Object item : (Object[]) obj) { |
|||
collectSensitiveWords(item, sensitiveWords); |
|||
} |
|||
} |
|||
} |
|||
else { |
|||
// 检查对象的所有字段 |
|||
checkObjectFields(obj, obj.getClass(), sensitiveWords); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 检查对象字段 |
|||
*/ |
|||
private void checkObjectFields(Object obj, Class<?> clazz, Set<String> sensitiveWords) { |
|||
// 基本类型不检查 |
|||
if (clazz.isPrimitive() || clazz == Integer.class || clazz == Long.class || |
|||
clazz == Double.class || clazz == Float.class || clazz == Boolean.class || |
|||
clazz == Byte.class || clazz == Character.class || clazz == Short.class || |
|||
clazz == Date.class) { |
|||
return; |
|||
} |
|||
|
|||
// 检查当前类的所有字段 |
|||
while (clazz != null && clazz != Object.class) { |
|||
Field[] fields = clazz.getDeclaredFields(); |
|||
for (Field field : fields) { |
|||
// 跳过静态字段 |
|||
if (java.lang.reflect.Modifier.isStatic(field.getModifiers())) { |
|||
continue; |
|||
} |
|||
|
|||
field.setAccessible(true); |
|||
try { |
|||
Object fieldValue = field.get(obj); |
|||
if (fieldValue != null) { |
|||
collectSensitiveWords(fieldValue, sensitiveWords); |
|||
} |
|||
} catch (IllegalAccessException e) { |
|||
// 忽略访问异常 |
|||
} |
|||
} |
|||
clazz = clazz.getSuperclass(); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 处理结果 - 修改版:敏感词列表放在msg中 |
|||
*/ |
|||
private Object handleResult(Set<String> sensitiveWords, SensitiveCheck sensitiveCheck) { |
|||
// 转为List并排序 |
|||
List<String> wordList = new ArrayList<>(sensitiveWords); |
|||
Collections.sort(wordList); |
|||
|
|||
// 构建消息:内容包含敏感词[词1,词2,词3] |
|||
String message = buildMessage(wordList); |
|||
|
|||
if (sensitiveCheck.throwException()) { |
|||
// 抛出异常 |
|||
throw new ServiceException(message, 400); |
|||
} else { |
|||
// 直接返回,敏感词列表在msg中 |
|||
return AjaxResult.error(message); |
|||
} |
|||
} |
|||
|
|||
/** |
|||
* 构建消息:内容包含敏感词[词1,词2,词3] |
|||
*/ |
|||
private String buildMessage(List<String> wordList) { |
|||
if (wordList.isEmpty()) { |
|||
return "内容包含敏感词"; |
|||
} |
|||
|
|||
StringBuilder sb = new StringBuilder(); |
|||
sb.append("内容包含敏感词["); |
|||
|
|||
for (int i = 0; i < wordList.size(); i++) { |
|||
if (i > 0) { |
|||
sb.append(","); |
|||
} |
|||
sb.append(wordList.get(i)); |
|||
} |
|||
|
|||
sb.append("]"); |
|||
return sb.toString(); |
|||
} |
|||
} |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue