| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199 |
- package com.zhentao.controller;
- import com.zhentao.service.YidunSecurityService;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.http.MediaType;
- import org.springframework.web.bind.annotation.PostMapping;
- import org.springframework.web.bind.annotation.RequestMapping;
- import org.springframework.web.bind.annotation.ResponseBody;
- import org.springframework.web.bind.annotation.RestController;
- import javax.servlet.http.HttpServletRequest;
- import java.io.*;
- import java.nio.charset.StandardCharsets;
- import java.util.Arrays;
- import java.util.List;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
- /**
- * 内容安全检测控制器
- * 用于检测用户发布的文字、图片是否包含违规内容
- * 使用网易易盾内容安全API
- */
- @RestController
- @RequestMapping("/api/content-security")
- public class ContentSecurityController {
- private static final Logger logger = LoggerFactory.getLogger(ContentSecurityController.class);
- // 注入网易易盾内容安全服务
- private final YidunSecurityService yidunSecurityService;
- // 构造函数注入
- public ContentSecurityController(YidunSecurityService yidunSecurityService) {
- this.yidunSecurityService = yidunSecurityService;
- }
- private static final List<String> SENSITIVE_WORDS = Arrays.asList(
- "色情", "裸体", "性爱", "约炮", "一夜情", "援交", "卖淫", "嫖娼", "小姐服务",
- "做爱", "性交", "口交", "肛交", "自慰", "手淫",
- "傻逼", "操你", "草泥马", "妈的", "他妈的", "狗日的", "王八蛋", "贱人", "婊子",
- "滚蛋", "去死", "废物", "白痴", "智障",
- "赌博", "毒品", "枪支", "炸弹", "恐怖", "暴力", "杀人", "自杀",
- "刷单", "兼职日结", "高额返利", "免费领取", "中奖", "彩票内幕", "稳赚不赔",
- "法轮功", "邪教"
- );
- /**
- * 检测文字内容是否安全
- */
- @PostMapping(value = "/check-text", produces = MediaType.APPLICATION_JSON_VALUE)
- @ResponseBody
- public String checkText(HttpServletRequest request) {
- String content = null;
- try {
- String body = readRequestBody(request);
- content = getJsonString(body, "content");
- } catch (Exception e) {
- logger.error("读取文字检测请求体失败", e);
- return buildResponse(false, "请求参数解析失败");
- }
- if (content == null || content.trim().isEmpty()) {
- return buildResponse(true, "");
- }
- logger.info("开始检测文字内容,长度: {}", content.length());
- // 第一层:本地敏感词快速检测
- String localCheckResult = localTextCheck(content);
- if (localCheckResult != null) {
- logger.info("本地敏感词检测不通过: {}", localCheckResult);
- return buildResponse(false, "内容包含敏感词,请修改后重试");
- }
- // 第二层:网易易盾内容安全检测(AI智能检测)
- try {
- String yidunResult = yidunSecurityService.checkText(content);
- if (yidunResult != null) {
- logger.info("网易易盾内容安全检测不通过: {}", yidunResult);
- return buildResponse(false, yidunResult);
- }
- } catch (Exception e) {
- logger.error("网易易盾文字内容安全检测异常", e);
- }
- logger.info("文字内容检测通过(已通过本地+网易易盾检测)");
- return buildResponse(true, "");
- }
- /**
- * 检测图片是否安全
- * 使用网易易盾内容安全API进行检测
- */
- @PostMapping(value = "/check-image", produces = MediaType.APPLICATION_JSON_VALUE)
- @ResponseBody
- public String checkImage(HttpServletRequest request) {
- String imageUrl = null;
- try {
- String body = readRequestBody(request);
- logger.info("收到图片检测请求: {}", body);
- imageUrl = getJsonString(body, "imageUrl");
- } catch (Exception e) {
- logger.error("读取图片检测请求体失败", e);
- return buildResponse(false, "请求参数错误");
- }
- if (imageUrl == null || imageUrl.trim().isEmpty()) {
- logger.warn("图片URL为空,跳过检测");
- return buildResponse(true, "");
- }
- logger.info("开始检测图片: {}", imageUrl);
- // 使用网易易盾图片内容安全检测
- try {
- String yidunResult = yidunSecurityService.checkImage(imageUrl);
- if (yidunResult != null) {
- logger.info("网易易盾图片检测不通过: {}", yidunResult);
- return buildResponse(false, yidunResult);
- }
- } catch (Exception e) {
- logger.error("网易易盾图片内容安全检测异常", e);
- }
- logger.info("图片检测通过: {}", imageUrl);
- return buildResponse(true, "");
- }
- /**
- * 构建统一JSON响应体
- */
- private String buildResponse(boolean safe, String message) {
- return "{\"code\":200,\"message\":\"成功\",\"data\":{\"safe\":" + safe +
- ",\"message\":\"" + escapeJson(message) + "\"},\"timestamp\":" +
- System.currentTimeMillis() + "}";
- }
- /**
- * 读取request请求体
- */
- private String readRequestBody(HttpServletRequest request) throws IOException {
- StringBuilder sb = new StringBuilder();
- try (BufferedReader reader = request.getReader()) {
- String line;
- while ((line = reader.readLine()) != null) {
- sb.append(line);
- }
- }
- return sb.toString();
- }
- /**
- * 本地敏感词检测-忽略大小写
- */
- private String localTextCheck(String content) {
- String lowerContent = content.toLowerCase();
- for (String word : SENSITIVE_WORDS) {
- if (lowerContent.contains(word.toLowerCase())) {
- return word;
- }
- }
- return null;
- }
- // ====================== 通用工具方法 ======================
- /**
- * 标准JSON字符串转义,补全所有缺失的转义字符
- */
- private String escapeJson(String str) {
- if (str == null) return "";
- StringBuilder sb = new StringBuilder();
- for (char c : str.toCharArray()) {
- switch (c) {
- case '\"': sb.append("\\\""); break;
- case '\\': sb.append("\\\\"); break;
- case '/': sb.append("\\/"); break;
- case '\b': sb.append("\\b"); break;
- case '\f': sb.append("\\f"); break;
- case '\n': sb.append("\\n"); break;
- case '\r': sb.append("\\r"); break;
- case '\t': sb.append("\\t"); break;
- default: sb.append(c); break;
- }
- }
- return sb.toString();
- }
- /**
- * 正则解析JSON字符串中的字符串值,兼容空格/换行
- */
- private String getJsonString(String json, String key) {
- if (json == null || key == null) return null;
- Pattern pattern = Pattern.compile("\"" + key + "\"\\s*:\\s*\"([^\"]*)\"");
- Matcher matcher = pattern.matcher(json);
- return matcher.find() ? matcher.group(1) : null;
- }
- }
|