内容安全
受众:开发者 摘要:Content Safety starter 使用方式、Provider 抽象、keyword / noop / 云端 provider 和自建 AI 模型内容安全接入边界。
Content Safety starter 提供统一的敏感内容检测入口,用于 Blog、Forum、Chat、Mall 评价、用户资料、广告素材等场景。
Content Safety starter 保持轻量:内置 keyword、noop、openai、google、aliyun、tencent、volcengine、baidu、ai-model 和 self-hosted provider,不引入重量级第三方内容安全 SDK。配置和代码边界按短信、存储等模块的 Provider 模式设计,后续新增内容安全服务商时继续通过 Provider 扩展。
后台敏感词库、检测日志、人工复核任务、批量扫描、文件扫描和 CSV 导出由 spring-open-core-content-safety 承接;后台 API 统一挂载在 /api/v1/content-safety/**,权限字符串使用 content-safety:*,配置前缀使用 spring.open.content-safety.*。
何时使用
适合:
- 发布前检测文本、昵称、签名、评论、聊天消息和视频内容元数据。
- 按场景决定通过、拒绝或进入人工审核。
- 给内容审核、违规日志、通知事件和广告素材审核提供统一底座。
- 给 Video 等业务模块提供统一
action/riskLevel/reason摘要,由业务模块自行决定公开过滤、待复核展示和播放地址隐藏。 - 后续替换或组合多个内容安全服务商。
不适合:
- 全局粗暴拦截所有请求体。
- 替代富文本 XSS 清洗。
- 在业务模块里直接调用第三方内容安全 SDK。
- 把聊天实时消息强制绑定慢速同步检测。
快速开始
按需引入:
<dependency>
<groupId>com.springopen</groupId>
<artifactId>spring-open-starter-content-safety</artifactId>
</dependency>默认启用,未配置敏感词时 keyword provider 会直接通过:
spring:
open:
content-safety:
default-provider: keyword
providers:
keyword:
provider: keyword
keywords:
- spam
- blockedkeyword provider 的词有两个来源,可同时生效:
- 配置词:上面的
keywords/regexes列表,按 provider 级action-on-match/risk-level-on-match统一决策。 - 词源 SPI(
ContentSafetyKeywordSource):业务侧注册的扩展词源,每条词自带matchType(keyword / regex)、riskLevel和action,按词级语义决策。装配spring-open-core-content-safety后,后台敏感词管理(content_safety_word表)会通过内置的数据库词源自动接入:管理员在后台增删改敏感词后最长 30 秒内对所有内容检测生效;action=reject直接拒绝,action=review转待复核。词源读库失败时沿用上一份词快照,不阻断内容发布。
配置词与词源词同时命中时整体动作取最严(reject 优先于 review),风险等级取命中项中的最高级。
Facade 使用:
ContentSafetyResult result = ContentSafety.check(ContentSafetyRequest.builder()
.scene("forum.topic")
.bizType("forum-topic")
.content("hello")
.build());
if (result.isRejected()) {
// 拒绝发布
}
if (result.isReviewRequired()) {
// 进入人工审核
}Provider
配置结构:
spring:
open:
content-safety:
enabled: true
default-provider: keyword
fallback-providers:
- noop
providers:
keyword:
provider: keyword
enabled: true
word-set: default
keywords:
- blocked
action-on-match: review
noop:
provider: noop
enabled: true
openai-main:
provider: openai
enabled: false
api-key: ${OPENAI_API_KEY:}
model: omni-moderation-latest
google-main:
provider: google
enabled: false
access-token: ${GOOGLE_CLOUD_LANGUAGE_ACCESS_TOKEN:}
aliyun-main:
provider: aliyun
enabled: false
endpoint: https://green-cip.cn-shanghai.aliyuncs.com
service: comment_detection_pro
access-key-id: ${ALIYUN_CONTENT_SAFETY_ACCESS_KEY_ID:}
access-key-secret: ${ALIYUN_CONTENT_SAFETY_ACCESS_KEY_SECRET:}
tencent-main:
provider: tencent
enabled: false
region: ap-guangzhou
biz-type: TencentCloudDefault
secret-id: ${TENCENT_CONTENT_SAFETY_SECRET_ID:}
secret-key: ${TENCENT_CONTENT_SAFETY_SECRET_KEY:}
volcengine-main:
provider: volcengine
enabled: false
region: cn-north-1
service: content_security
access-key-id: ${VOLCENGINE_CONTENT_SAFETY_ACCESS_KEY_ID:}
access-key-secret: ${VOLCENGINE_CONTENT_SAFETY_ACCESS_KEY_SECRET:}
properties:
app-id: ${VOLCENGINE_CONTENT_SAFETY_APP_ID:}
baidu-main:
provider: baidu
enabled: false
access-token: ${BAIDU_CONTENT_SAFETY_ACCESS_TOKEN:}
local-model:
provider: ai-model
enabled: false
endpoint: ${LOCAL_CONTENT_SAFETY_ENDPOINT:}
api-key: ${LOCAL_CONTENT_SAFETY_API_KEY:}
model: moderation-v1
private-model:
provider: self-hosted
enabled: false
endpoint: ${PRIVATE_CONTENT_SAFETY_ENDPOINT:}
api-key: ${PRIVATE_CONTENT_SAFETY_API_KEY:}
model: moderation-v1说明:
providers的 map key 是可命名 provider 实例,例如keyword、keyword-strict、tencent-main。providers.*.provider是真实 provider 实现类型,例如keyword、noop、tencent、aliyun、volcengine、baidu、ai-model、self-hosted。- 同一个 provider 实现类型可以配置多个 provider 实例。
- 业务模块只调用
ContentSafety/ContentSafetyManager,不直接依赖第三方 SDK。
配置
| 配置 | 默认值 | 说明 |
|---|---|---|
spring.open.content-safety.enabled | true | 是否启用内容安全 starter |
spring.open.content-safety.default-provider | keyword | 默认 provider |
spring.open.content-safety.fallback-providers | noop | provider 不可用时的后备 provider |
spring.open.content-safety.providers.*.provider | - | provider 实例使用的实现类型 |
spring.open.content-safety.providers.*.enabled | true | provider 是否启用 |
spring.open.content-safety.providers.*.endpoint | 按 provider | 服务地址;OpenAI 默认 https://api.openai.com/v1/moderations,Google 默认 https://language.googleapis.com/v1/documents:moderateText,阿里云默认 https://green-cip.cn-shanghai.aliyuncs.com,腾讯云默认 https://tms.tencentcloudapi.com,火山默认 https://riskcontrol.volcengineapi.com,百度默认 https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined,自建模型必须显式配置 |
spring.open.content-safety.providers.*.timeout | 10s | HTTP 请求超时时间 |
spring.open.content-safety.providers.*.api-key | 空 | OpenAI / 自建模型等 Bearer Token |
spring.open.content-safety.providers.*.access-token | 空 | Google Cloud Natural Language OAuth Access Token 或百度内容审核 access token |
spring.open.content-safety.providers.*.model | 按 provider | OpenAI moderation 模型或自建模型名;OpenAI 默认 omni-moderation-latest |
spring.open.content-safety.providers.*.service | 按 provider | 阿里云 TextModerationPlus 服务或火山业务风险服务;阿里云默认 comment_detection_pro,火山默认 content_security |
spring.open.content-safety.providers.*.access-key-id | 空 | 阿里云 / 火山 AccessKey ID |
spring.open.content-safety.providers.*.access-key-secret | 空 | 阿里云 / 火山 AccessKey Secret |
spring.open.content-safety.providers.*.secret-id | 空 | 腾讯云 SecretId |
spring.open.content-safety.providers.*.secret-key | 空 | 腾讯云 SecretKey |
spring.open.content-safety.providers.*.region | 按 provider | 腾讯云 / 火山地域;腾讯云默认 ap-guangzhou,火山默认 cn-north-1 |
spring.open.content-safety.providers.*.biz-type | 按 provider | 腾讯云策略 BizType,默认 TencentCloudDefault |
spring.open.content-safety.providers.*.properties.app-id | 空 | 火山内容安全应用 ID |
spring.open.content-safety.providers.*.properties.action | TextSliceRisk | 火山 OpenAPI Action |
spring.open.content-safety.providers.*.properties.version | 按 provider | 火山 API Version 或云厂商扩展版本 |
spring.open.content-safety.providers.*.properties.signing-service | businessSecurity | 火山 OpenAPI 签名服务名 |
spring.open.content-safety.providers.*.keywords | 空 | keyword provider 使用的关键词 |
spring.open.content-safety.providers.*.regexes | 空 | keyword provider 使用的正则规则 |
spring.open.content-safety.providers.*.ignore-case | true | keyword / regex 是否忽略大小写 |
spring.open.content-safety.providers.*.action-on-match | review | 命中后的建议动作:allow / review / reject |
spring.open.content-safety.providers.*.risk-level-on-match | medium | 命中后的风险等级 |
OpenAI Provider
openai provider 对接 OpenAI Moderations API,适合作为国际化内容审核默认服务:
spring:
open:
content-safety:
default-provider: openai-main
providers:
openai-main:
provider: openai
enabled: true
api-key: ${OPENAI_API_KEY:}
model: omni-moderation-latest说明:
- 默认调用
https://api.openai.com/v1/moderations。 - 官方默认模型为
omni-moderation-latest。 - 命中后默认返回
review,如需直接拒绝可配置action-on-match: reject。 - OpenAI 返回的分类会转换为
ContentSafetyMatch,前端和业务模块不需要感知 OpenAI 原始响应结构。
参考:
Google Provider
google provider 对接 Google Cloud Natural Language documents:moderateText REST API,适合作为海外内容审核服务的可选方案:
spring:
open:
content-safety:
default-provider: google-main
providers:
google-main:
provider: google
enabled: true
access-token: ${GOOGLE_CLOUD_LANGUAGE_ACCESS_TOKEN:}说明:
- 默认调用
https://language.googleapis.com/v1/documents:moderateText。 - Google 官方接口要求 OAuth 授权,本框架不内置服务账号换 token 逻辑,避免引入较重 Google Auth SDK;部署时把外部获取到的短期 access token 注入配置即可。
moderationCategories会按置信度转换为统一ContentSafetyMatch;默认阈值为0.4,可通过properties.threshold调整。
参考:
Aliyun Provider
aliyun provider 对接阿里云内容安全 TextModerationPlus,适合作为国内内容审核服务的可选方案:
spring:
open:
content-safety:
default-provider: aliyun-main
providers:
aliyun-main:
provider: aliyun
enabled: true
endpoint: https://green-cip.cn-shanghai.aliyuncs.com
service: comment_detection_pro
access-key-id: ${ALIYUN_CONTENT_SAFETY_ACCESS_KEY_ID:}
access-key-secret: ${ALIYUN_CONTENT_SAFETY_ACCESS_KEY_SECRET:}说明:
- 默认调用
https://green-cip.cn-shanghai.aliyuncs.com。 - 请求使用阿里云 OpenAPI HMAC-SHA1 签名,不引入
green20220302SDK。 service可按场景切换,例如chat_detection_pro、comment_detection_pro、nickname_detection_pro、ugc_moderation_byllm等。Data.RiskLevel=low转为allow,medium转为review,high转为reject。
参考:
Tencent Provider
tencent provider 对接腾讯云 TMS TextModeration,适合作为国内内容审核服务:
spring:
open:
content-safety:
default-provider: tencent-main
providers:
tencent-main:
provider: tencent
enabled: true
region: ap-guangzhou
biz-type: TencentCloudDefault
secret-id: ${TENCENT_CONTENT_SAFETY_SECRET_ID:}
secret-key: ${TENCENT_CONTENT_SAFETY_SECRET_KEY:}说明:
- 默认调用
https://tms.tencentcloudapi.com。 - 请求使用腾讯云 TC3-HMAC-SHA256 签名。
Suggestion=Pass转为allow,Suggestion=Review转为review,Suggestion=Block转为reject。- 腾讯云返回的
Label、Keywords、Score会转换为统一ContentSafetyResult。
参考:
Volcengine Provider
volcengine provider 对接火山引擎业务风险识别文本风险接口,适合作为国内内容审核服务的可选方案:
spring:
open:
content-safety:
default-provider: volcengine-main
providers:
volcengine-main:
provider: volcengine
enabled: true
endpoint: https://riskcontrol.volcengineapi.com
region: cn-north-1
service: content_security
access-key-id: ${VOLCENGINE_CONTENT_SAFETY_ACCESS_KEY_ID:}
access-key-secret: ${VOLCENGINE_CONTENT_SAFETY_ACCESS_KEY_SECRET:}
properties:
app-id: ${VOLCENGINE_CONTENT_SAFETY_APP_ID:}说明:
- 默认请求
Action=TextSliceRisk、Version=2022-11-07,通过properties.app-id传递火山应用 ID。 - 请求使用火山 OpenAPI HMAC-SHA256 签名,不引入火山 SDK。
Decision=Pass转为allow,Block/Reject转为reject,其他风险决策默认转为review。Data.Results、FinalLabel、DecisionLabel、Score会转换为统一ContentSafetyResult。
参考:
Baidu Provider
baidu provider 对接百度智能云内容审核平台文本接口:
spring:
open:
content-safety:
default-provider: baidu-main
providers:
baidu-main:
provider: baidu
enabled: true
access-token: ${BAIDU_CONTENT_SAFETY_ACCESS_TOKEN:}说明:
- 默认调用
https://aip.baidubce.com/rest/2.0/solution/v1/text_censor/v2/user_defined。 - 百度接口使用
access_token鉴权;本框架不内置 token 换取和刷新逻辑,部署时由外部任务把有效 token 注入配置。 conclusionType=1转为allow,2转为reject,3转为review,4视为 provider 调用失败。data[].hits[].words会脱敏后转换为统一ContentSafetyMatch。
参考:
AI Model Provider
ai-model / self-hosted provider 面向自建或内网模型服务,使用轻量 HTTP JSON contract,避免 starter 直接绑定具体模型 SDK。两者使用同一请求 / 响应协议;self-hosted 更适合作为私有模型网关的业务可见 provider 名:
spring:
open:
content-safety:
default-provider: local-model
providers:
local-model:
provider: ai-model
enabled: true
endpoint: https://model.example.internal/moderations
api-key: ${LOCAL_CONTENT_SAFETY_API_KEY:}
model: moderation-v1请求体会发送 model、input、contentType、scene、bizType 和请求扩展属性。响应支持以下轻量字段:
{
"action": "review",
"riskLevel": "medium",
"reason": "custom-model.flagged",
"matches": [
{"type": "label", "category": "spam", "keyword": "coupon", "score": 0.72}
]
}说明:
allowed=true或action=allow|pass且无高风险时转为allow。action=reject|block|deny或riskLevel=high转为reject。- 其他命中默认转为
review。
Provider 选择顺序
未显式指定 provider 时,Manager 按顺序选择:
ContentSafetyRouteResolver返回的候选 provider。default-provider。fallback-providers。
显式指定 provider 时,只使用该 provider。
源码机制骨架
| 类型 | 机制职责 |
|---|---|
ContentSafety | 静态 Facade,给业务模块提供最短检测入口 |
ContentSafetyManagerProvider | 将 Facade 绑定到 Spring 容器内的 ContentSafetyManager |
ContentSafetyManager | 检测编排入口,负责请求校验、provider 路由、fallback、事件通知和异常语义 |
DefaultContentSafetyManager | 默认 Manager 实现,按显式 provider、路由解析器、默认 provider、fallback provider 的顺序生成候选列表 |
ContentSafetyRouteResolver | 场景化 provider 路由扩展点,可按 scene、bizType、用户、语言或租户返回候选 provider |
ContentSafetyProvider | Provider SPI,只负责调用具体检测策略或外部服务并返回统一结果 |
ContentSafetyProviderContext | 已解析的 provider 实例上下文,区分配置实例名和实现类型 |
ContentSafetyCheckListener | 检测事件监听器,用于审计、统计或复核任务生成;监听器失败不影响检测结果 |
ContentSafetyCheckEvent | 检测事件,记录候选 provider、最终 provider、结果、异常和耗时 |
ContentSafetyRequest | 检测请求,只描述业务场景、对象标识、内容类型和待检测文本 |
ContentSafetyResult | 统一结果,返回 allow / review / reject 建议、风险等级、命中摘要和轻量 metadata |
Provider 实例名和实现类型是两个概念:tencent-main、tencent-strict 可以都是 provider: tencent。Manager 先按实例名读取配置,再用实现类型找到对应 ContentSafetyProvider。
检测成功或最终失败后都会触发 ContentSafetyCheckListener;监听器异常会被吞掉,不能反向阻塞用户发布、评论或聊天发送。
复杂场景建议写 ContentSafetyRouteResolver,不要在 YAML 里堆路由 DSL:
@Bean
ContentSafetyRouteResolver contentSafetyRouteResolver() {
return request -> {
if ("chat.message".equals(request.getScene())) {
return List.of("keyword-chat");
}
return List.of();
};
}检测事件监听
每次内容安全检测最终成功或失败后,Manager 会发布 ContentSafetyCheckEvent 给所有 ContentSafetyCheckListener。
这个扩展点用于后续落库检测日志、运营审计、失败统计和审核任务生成。Listener 失败不会影响本次内容安全判断,避免日志系统异常反向阻塞用户发布、评论或聊天链路。
@Bean
ContentSafetyCheckListener contentSafetyCheckListener() {
return event -> {
// event.request():业务场景、bizType、bizId、用户和内容类型
// event.providerCandidates():本次候选 provider
// event.result():最终检测结果
// event.exception():最终失败异常
// event.elapsed():检测耗时
};
}业务模块仍然只关心 ContentSafetyResult 的建议动作;检测日志、审核任务和运维报表由 spring-open-core-content-safety 通过 Listener 承接,业务模块只按需贡献批量检测来源或消费检测结果。
已接入模块
当前已有这些业务模块消费内容安全底座:
| 模块 | 场景 | reject | review |
|---|---|---|---|
| Blog | 文章发布 / 编辑、评论提交 | 拒绝保存并返回业务错误 | 文章转为草稿,评论转为隐藏 |
| Forum | 主题发布 / 编辑、回复提交 | 拒绝保存并返回业务错误 | 主题 / 回复转为隐藏 |
| Conversation | 聊天消息发送、附件名称检测 | 拒绝发送,不落库、不推送 | 阻断发送,提示内容需调整 |
| CMS | 后台批量检测 cms-content 来源 | 不直接修改业务内容 | 检测日志进入内容安全复核队列 |
| Mall | 后台批量检测 mall-review 来源 | 不直接修改商品评价 | 检测日志进入内容安全复核队列 |
检测日志由 spring-open-core-content-safety 监听器统一落库,仅记录业务场景、Provider、动作、风险等级、耗时、长度等元数据,不保存被检测标题或正文原文。
聊天消息是实时体验,第一阶段不引入“已发送但待审核”的中间态。消息文本和附件名称会在消息落库、附件绑定、未读更新和 WebSocket 推送前统一检测;命中 reject 或 review 都直接阻断发送。
后台批量检测调度只负责重新触发检测和生成检测日志,不直接改 CMS 内容、Blog 文章 / 评论或 Mall 评价状态。当前支持这些 sourceType:
cms-content:CMS 内容标题、摘要、正文和 SEO 摘要。blog-article:Blog 文章标题、摘要、付费试看和正文。blog-comment:Blog 评论昵称和正文。mall-review:商城评价商品名称、评价正文和商家回复。
内容安全运维日志
spring-open-core-content-safety 已内置检测日志落库监听器。每次内容安全检测成功或失败后,会记录检测元数据到 content_safety_check_log:
- 记录
scene/bizType/bizId/contentType/userId。 - 记录 provider 候选、最终 provider、动作、风险等级、命中数量、耗时和异常摘要。
- 不记录被检测的标题或正文原文,只记录标题长度和正文长度,避免敏感内容二次沉淀。
后台运维接口:
| 方法 | 路径 | 说明 |
|---|---|---|
POST | /api/v1/admin/content-safety/batch-scans | 按业务来源批量触发内容安全检测 |
GET | /api/v1/content-safety/words | 分页查询敏感词库 |
GET | /api/v1/content-safety/words/{id} | 查询敏感词详情 |
POST | /api/v1/content-safety/words | 新增敏感词 |
PUT | /api/v1/content-safety/words/{id} | 更新敏感词 |
POST | /api/v1/content-safety/words/{id}/enable | 启用敏感词 |
POST | /api/v1/content-safety/words/{id}/disable | 停用敏感词 |
DELETE | /api/v1/content-safety/words/{id} | 删除敏感词 |
DELETE | /api/v1/content-safety/words | 批量删除敏感词 |
GET | /api/v1/content-safety/check-logs | 分页查询检测日志 |
GET | /api/v1/content-safety/check-logs/{id} | 查询检测日志详情 |
GET | /api/v1/content-safety/review-tasks | 分页查询需要人工复核的检测任务 |
GET | /api/v1/content-safety/review-tasks/{id} | 查询需要人工复核的检测任务详情 |
POST | /api/v1/content-safety/review-tasks/{id}/approve | 将复核任务标记为已通过 |
POST | /api/v1/content-safety/review-tasks/{id}/reject | 将复核任务标记为已拒绝 |
POST | /api/v1/content-safety/review-tasks/{id}/close | 将复核任务标记为已关闭 |
POST | /api/v1/content-safety/review-tasks/batch/approve | 批量将复核任务标记为已通过 |
POST | /api/v1/content-safety/review-tasks/batch/reject | 批量将复核任务标记为已拒绝 |
POST | /api/v1/content-safety/review-tasks/batch/close | 批量将复核任务标记为已关闭 |
POST | /api/v1/content-safety/review-tasks/auto-handle-expired | 按配置批量处理超时仍未人工复核的任务 |
权限:
content-safety:check-log:viewcontent-safety:word:viewcontent-safety:word:createcontent-safety:word:updatecontent-safety:word:deletecontent-safety:review-task:viewcontent-safety:review-task:update
敏感词库写入 content_safety_word,同一 wordSet + word 保持唯一;每条规则可维护分类、风险等级、匹配类型、命中动作、启停状态和说明。wordSet 默认 default,category 默认 general,风险等级默认 medium,匹配类型默认 keyword,命中动作默认 review。
审核任务入口复用检测日志中 reviewRequired=true 的记录,不额外保存被检测原文。单条和批量复核动作都会通过审批工作流 content-safety.review 校验来源状态、动作、权限快照和备注要求,再只记录 reviewStatus / reviewAction / reviewRemark / reviewedBy / reviewedAt 审计字段,不直接修改 Blog、Forum、Chat、Mall 等业务对象状态;业务侧具体放行、拒绝或超时处理继续由各模块自己的审核状态机或事件联动承接。
reject 要求填写备注,approve / close 可不填备注。人工动作要求调用方具备 content-safety:review-task:update 权限;超时自动处理使用 auto-approve / auto-reject / auto-close 动作,不携带人工操作人。
超时自动处理默认启用,默认动作是 approve,符合“审核未及时处理时默认放行”的开发体验。若业务场景更敏感,可以改为 reject 或 close:
spring:
open:
content-safety:
review:
auto:
enabled: true
auto-startup: false
timeout: 24h
fixed-delay: 10m
action: approve
limit: 100
remark: 内容安全复核超时自动通过检测日志落库且需要人工复核时,系统会按 timeout 向专用 content-safety 队列投递 content-safety.review.auto-handle 延迟 Queue 消息;消费时会重新读取复核状态,已经人工处理或不再满足复核条件的记录会安全跳过。auto-startup 和 fixed-delay 仅作为旧固定间隔调度配置保留,默认不再注册周期扫描。后台也可以手动调用 POST /api/v1/content-safety/review-tasks/auto-handle-expired 立即处理一批超时任务。
自动处理只更新内容安全复核审计字段:
reviewStatus:按action写入approved/rejected/closed。reviewAction:写入auto-approve/auto-reject/auto-close。reviewRemark:写入配置的自动处理备注。reviewedBy:为空,表示系统自动处理。reviewedAt:自动处理时间。
Admin 后台已接入两个运维页面:
| 页面 | 路由 | 能力 |
|---|---|---|
| 内容安全词库 | /#/content-safety/words | 分页、筛选、详情、新增 / 编辑、启用 / 停用、删除 / 批量删除敏感词,并展示词库、分类、风险等级、匹配类型和命中动作 |
| 内容安全检测日志 | /#/content-safety/check-logs | 分页、筛选、详情、结果状态展示、业务快捷筛选、图片文件批量检测、按当前筛选创建 CSV 导出异步任务,并可把需要复核的记录带入同一业务筛选条件跳转到复核任务页 |
| 内容安全复核任务 | /#/content-safety/review-tasks | 分页、筛选、接收检测日志页 URL 筛选、业务快捷筛选、详情、通过 / 拒绝 / 关闭复核、批量通过 / 拒绝 / 关闭复核、按当前筛选创建 CSV 导出异步任务、手动触发超时自动处理和检测日志跳转 |
业务快捷筛选只暴露已经真实接入内容安全 contract 的来源。后端已提供 /api/v1/admin/content-safety/batch-scans 统一触发 CMS 内容、Blog 文章、Blog 评论和 Mall 评价批量检测;Admin 视图后续可按该 contract 接入来源选择和触发按钮,不伪造本地预览数据。
Keyword Provider
keyword provider 支持:
- 普通关键词匹配。
- 正则匹配。
- 大小写忽略。
- 命中后返回
review或reject。 - 命中词脱敏返回,避免检测结果泄露完整敏感词。
未配置关键词和正则时,keyword provider 直接通过。
Noop Provider
noop provider 始终通过,适合:
- 开发环境。
- 未启用真实内容安全时的 fallback。
- 单进程隔离诊断或兼容模式。
生产环境不建议只依赖 noop。
后续接入
后续第三方 provider 按同一边界扩展:
volcengine:火山引擎内容安全。baidu:百度智能云内容审核。ai-model:AI Model 底座成熟后的模型审核。self-hosted:私有化部署或内网自建模型审核服务。
第三方 SDK 只出现在对应 provider 实现内部,不向 Controller、Service、DTO 或业务模块泄露。
与审核关系
内容安全只给出建议动作:
allow:可通过。review:进入人工审核。reject:拒绝。
Blog / Forum 第一阶段会先把 review 内容转为草稿或隐藏;Conversation 会在发送前阻断。人工审核任务、审核超时默认动作、审核日志和通知事件由 spring-open-core-content-safety 承接,业务侧具体状态流转继续由各业务模块处理。
验证
./mvnw -pl spring-open-starters/spring-open-starter-content-safety -am test -DskipITs
git diff --check