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 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; } }