mirror of
https://github.com/continew-org/continew-starter.git
synced 2025-09-09 08:57:17 +08:00
refactor(security/sensitivewords): 优化敏感词模块代码
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>top.continew</groupId>
|
||||
<artifactId>continew-starter-security</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>continew-starter-security-sensitivewords</artifactId>
|
||||
<description>ContiNew Starter 安全模块 - 敏感词模块</description>
|
||||
|
||||
<dependencies>
|
||||
<!-- Hutool DFA 模块(基于 DFA 的关键词查找) -->
|
||||
<dependency>
|
||||
<groupId>cn.hutool</groupId>
|
||||
<artifactId>hutool-dfa</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-validation</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.security.sensitivewords.autoconfigure;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.boot.autoconfigure.AutoConfiguration;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.boot.context.properties.EnableConfigurationProperties;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import top.continew.starter.security.sensitivewords.service.DefaultSensitiveWordsConfig;
|
||||
import top.continew.starter.security.sensitivewords.service.DefaultSensitiveWordsService;
|
||||
import top.continew.starter.security.sensitivewords.service.SensitiveWordsConfig;
|
||||
import top.continew.starter.security.sensitivewords.service.SensitiveWordsService;
|
||||
|
||||
/**
|
||||
* 敏感词自动配置
|
||||
*
|
||||
* @author luoqiz
|
||||
* @author Charles7c
|
||||
* @since 2.9.0
|
||||
*/
|
||||
@AutoConfiguration
|
||||
@EnableConfigurationProperties(SensitiveWordsProperties.class)
|
||||
public class SensitiveWordsAutoConfiguration {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SensitiveWordsAutoConfiguration.class);
|
||||
|
||||
/**
|
||||
* 默认敏感词配置
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SensitiveWordsConfig sensitiveWordsConfig(SensitiveWordsProperties properties) {
|
||||
return new DefaultSensitiveWordsConfig(properties);
|
||||
}
|
||||
|
||||
/**
|
||||
* 默认敏感词服务
|
||||
*/
|
||||
@Bean
|
||||
@ConditionalOnMissingBean
|
||||
public SensitiveWordsService sensitiveWordsService(SensitiveWordsConfig sensitiveWordsConfig) {
|
||||
return new DefaultSensitiveWordsService(sensitiveWordsConfig);
|
||||
}
|
||||
|
||||
@PostConstruct
|
||||
public void postConstruct() {
|
||||
log.debug("[ContiNew Starter] - Auto Configuration 'Security-Sensitive Words' completed initialization.");
|
||||
}
|
||||
}
|
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.security.sensitivewords.autoconfigure;
|
||||
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import top.continew.starter.core.constant.PropertiesConstants;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 敏感词配置属性
|
||||
*
|
||||
* @author luoqiz
|
||||
* @author Charles7c
|
||||
* @since 2.9.0
|
||||
*/
|
||||
@ConfigurationProperties(PropertiesConstants.SECURITY_SENSITIVE_WORDS)
|
||||
public class SensitiveWordsProperties {
|
||||
|
||||
/**
|
||||
* 敏感词列表
|
||||
*/
|
||||
private List<String> values;
|
||||
|
||||
public List<String> getValues() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public void setValues(List<String> values) {
|
||||
this.values = values;
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.security.sensitivewords.service;
|
||||
|
||||
import top.continew.starter.security.sensitivewords.autoconfigure.SensitiveWordsProperties;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 默认敏感词配置
|
||||
*
|
||||
* @author luoqiz
|
||||
* @author Charles7c
|
||||
* @since 2.9.0
|
||||
*/
|
||||
public class DefaultSensitiveWordsConfig implements SensitiveWordsConfig {
|
||||
|
||||
private final SensitiveWordsProperties properties;
|
||||
|
||||
public DefaultSensitiveWordsConfig(SensitiveWordsProperties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getWords() {
|
||||
if (properties.getValues() != null) {
|
||||
return properties.getValues();
|
||||
}
|
||||
return List.of();
|
||||
}
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.security.sensitivewords.service;
|
||||
|
||||
import cn.hutool.dfa.WordTree;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 默认敏感词服务
|
||||
*
|
||||
* @author luoqiz
|
||||
* @author Charles7c
|
||||
* @since 2.9.0
|
||||
*/
|
||||
@ConditionalOnBean(SensitiveWordsConfig.class)
|
||||
@ConditionalOnMissingBean(SensitiveWordsService.class)
|
||||
public class DefaultSensitiveWordsService implements SensitiveWordsService {
|
||||
|
||||
private final SensitiveWordsConfig sensitiveWordsConfig;
|
||||
private final WordTree tree = new WordTree();
|
||||
|
||||
public DefaultSensitiveWordsService(SensitiveWordsConfig sensitiveWordsConfig) {
|
||||
this.sensitiveWordsConfig = sensitiveWordsConfig;
|
||||
if (sensitiveWordsConfig != null && sensitiveWordsConfig.getWords() != null) {
|
||||
tree.addWords(sensitiveWordsConfig.getWords());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> check(String content) {
|
||||
return tree.matchAll(content, -1, false, true);
|
||||
}
|
||||
}
|
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.security.sensitivewords.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 敏感词配置接口
|
||||
*
|
||||
* @author luoqiz
|
||||
* @author Charles7c
|
||||
* @since 2.9.0
|
||||
*/
|
||||
public interface SensitiveWordsConfig {
|
||||
|
||||
/**
|
||||
* 获取敏感词列表
|
||||
*
|
||||
* @return 敏感词列表
|
||||
*/
|
||||
List<String> getWords();
|
||||
}
|
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.security.sensitivewords.service;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 敏感词服务接口
|
||||
*
|
||||
* @author luoqiz
|
||||
* @author Charles7c
|
||||
* @since 2.9.0
|
||||
*/
|
||||
public interface SensitiveWordsService {
|
||||
|
||||
/**
|
||||
* 检查敏感词
|
||||
*
|
||||
* @param content 待检测字符串
|
||||
* @return 敏感词列表
|
||||
*/
|
||||
List<String> check(String content);
|
||||
}
|
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.security.sensitivewords.validation;
|
||||
|
||||
import jakarta.validation.Constraint;
|
||||
import jakarta.validation.Payload;
|
||||
|
||||
import java.lang.annotation.*;
|
||||
|
||||
/**
|
||||
* 敏感词注解
|
||||
*
|
||||
* @author luoqiz
|
||||
* @author Charles7c
|
||||
* @since 2.9.0
|
||||
*/
|
||||
@Target({ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.PARAMETER, ElementType.TYPE_USE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Constraint(validatedBy = {SensitiveWordsValidator.class})
|
||||
public @interface SensitiveWords {
|
||||
|
||||
/**
|
||||
* 提示消息
|
||||
*
|
||||
* @return 提示消息
|
||||
*/
|
||||
String message() default "内容包含敏感词汇";
|
||||
|
||||
/**
|
||||
* 分组
|
||||
*
|
||||
* @return 分组
|
||||
*/
|
||||
Class<?>[] groups() default {};
|
||||
|
||||
/**
|
||||
* 负载
|
||||
*
|
||||
* @return 负载
|
||||
*/
|
||||
Class<? extends Payload>[] payload() default {};
|
||||
}
|
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2022-present Charles7c Authors. All Rights Reserved.
|
||||
* <p>
|
||||
* Licensed under the GNU LESSER GENERAL PUBLIC LICENSE 3.0;
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p>
|
||||
* http://www.gnu.org/licenses/lgpl.html
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package top.continew.starter.security.sensitivewords.validation;
|
||||
|
||||
import jakarta.annotation.Resource;
|
||||
import jakarta.validation.ConstraintValidator;
|
||||
import jakarta.validation.ConstraintValidatorContext;
|
||||
import top.continew.starter.security.sensitivewords.service.SensitiveWordsService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 敏感词校验器
|
||||
*
|
||||
* @author luoqiz
|
||||
* @author Charles7c
|
||||
* @since 2.9.0
|
||||
*/
|
||||
public class SensitiveWordsValidator implements ConstraintValidator<SensitiveWords, String> {
|
||||
|
||||
@Resource
|
||||
private SensitiveWordsService sensitiveWordsService;
|
||||
|
||||
@Override
|
||||
public boolean isValid(String value, ConstraintValidatorContext context) {
|
||||
List<String> res = sensitiveWordsService.check(value);
|
||||
if (!res.isEmpty()) {
|
||||
// 禁用默认消息
|
||||
context.disableDefaultConstraintViolation();
|
||||
// 动态设置错误消息
|
||||
context.buildConstraintViolationWithTemplate("内容包含敏感词汇: " + String.join(",", res)).addConstraintViolation();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
top.continew.starter.security.sensitivewords.autoconfigure.SensitiveWordsAutoConfiguration
|
@@ -18,6 +18,7 @@
|
||||
<module>continew-starter-security-mask</module>
|
||||
<module>continew-starter-security-crypto</module>
|
||||
<module>continew-starter-security-limiter</module>
|
||||
<module>continew-starter-security-sensitivewords</module>
|
||||
</modules>
|
||||
|
||||
<dependencies>
|
||||
|
Reference in New Issue
Block a user