Browse Source

阿里安全检测

wxd 2 weeks ago
parent
commit
88a80f7209

+ 3 - 3
alien-second/src/main/java/shop/alien/second/service/impl/SecondGoodsServiceImpl.java

@@ -362,7 +362,7 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
             // 批量设置商品图片信息
 //            batchSetGoodsImages(searchGoodsList);
             // 批量设置用户信息
-            batchSetUserInfo(searchGoodsList);
+            batchSetSearchUserInfo(searchGoodsList);
             // 批量设置收藏状态
             batchSetCollectStatus(searchGoodsList,secondGoodsVo.getUserPhone(), userId);
             // 批量设置点赞状态
@@ -654,7 +654,7 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
      * 批量设置用户信息(用于SecondGoodsVo列表)
      * @param searchGoodsList 搜索结果
      */
-    private void batchSetUserInfo(IPage<SecondGoodsVo> searchGoodsList) {
+    private void batchSetSearchUserInfo(IPage<SecondGoodsVo> searchGoodsList) {
         batchSetUserInfo(searchGoodsList, 
                         SecondGoodsVo::getUserId,
                         (goods, userInfo) -> {
@@ -662,7 +662,7 @@ public class SecondGoodsServiceImpl extends ServiceImpl<SecondGoodsMapper, Secon
                             goods.setRealName(userInfo.getRealName());
                             goods.setUserImage(userInfo.getUserImage());
                             goods.setUserId(userInfo.getId());
-                            goods.setUserPhone(userInfo.getUserPhone());
+                            goods.setUserPhone("user_"+userInfo.getUserPhone());
                         });
     }
     

+ 6 - 0
alien-util/pom.xml

@@ -123,6 +123,12 @@
             <artifactId>easyexcel</artifactId>
             <version>1.1.2-beta5</version>
         </dependency>
+        <!--    阿里安全图片/文本检测    -->
+        <dependency>
+            <groupId>com.aliyun</groupId>
+            <artifactId>green20220302</artifactId>
+            <version>2.20.0</version>
+        </dependency>
 
         <!--openoffice-->
         <dependency>

+ 173 - 0
alien-util/src/main/java/shop/alien/util/common/safe/ImageModerationUtil.java

@@ -0,0 +1,173 @@
+package shop.alien.util.common.safe;
+import com.alibaba.fastjson.JSON;
+import com.aliyun.green20220302.Client;
+import com.aliyun.green20220302.models.ImageBatchModerationResponse;
+import com.aliyun.green20220302.models.ImageModerationRequest;
+import com.aliyun.green20220302.models.ImageModerationResponse;
+import com.aliyun.green20220302.models.ImageBatchModerationRequest;
+import com.aliyun.green20220302.models.ImageBatchModerationResponse;
+import com.aliyun.green20220302.models.ImageBatchModerationResponseBody;
+import com.aliyun.green20220302.models.ImageModerationResponseBody;
+import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyData;
+import com.aliyun.green20220302.models.ImageModerationResponseBody.ImageModerationResponseBodyDataResult;
+import com.aliyun.teaopenapi.models.Config;
+import com.aliyun.teautil.models.RuntimeOptions;
+import jdk.nashorn.internal.runtime.logging.Logger;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.UUID;
+
+@Logger
+public class ImageModerationUtil {
+
+    @Value("${ali.yundun.accessKeyID}")
+    private String accessKeyId;
+
+    @Value("${ali.yundun.secret}")
+    private String accessKeySecret;
+
+    @Value("${ali.yundun.imgEndpoint}")
+    private String ImgEndpoint;
+
+    /**
+     * 创建请求客户端
+     * @return  Client
+     * @throws Exception 创建客户端异常
+     */
+    public Client createClient() throws Exception {
+        Config config = new Config();
+        config.setAccessKeyId(accessKeyId);
+        config.setAccessKeySecret(accessKeySecret);
+        // 设置http代理。
+        //config.setHttpProxy("http://10.10.xx.xx:xxxx");
+        // 设置https代理。
+        //config.setHttpsProxy("https://10.10.xx.xx:xxxx");
+        // 接入区域和地址请根据实际情况修改
+        // 接入地址列表:https://help.aliyun.com/document_detail/467828.html?#section-uib-qkw-0c8
+        config.setEndpoint(ImgEndpoint);
+        return new Client(config);
+    }
+
+    /**
+     * 提供给service调用的方法
+     *
+     * @param imageUrl 图片地址
+     * @param serviceEnum Service类型
+     * @return 检测结果
+     * @throws Exception 检测异常
+     */
+    public ImageModerationResponse invokeFunction(String imageUrl,String serviceEnum) throws Exception {
+        //注意,此处实例化的client请尽可能重复使用,避免重复建立连接,提升检测性能。
+        Client client = createClient();
+
+        // 创建RuntimeObject实例并设置运行参数
+        RuntimeOptions runtime = new RuntimeOptions();
+
+        // 检测参数构造。
+        Map<String, String> serviceParameters = new HashMap<>();
+        //公网可访问的URL。
+        serviceParameters.put("imageUrl", imageUrl);
+        //待检测数据唯一标识
+        serviceParameters.put("dataId", UUID.randomUUID().toString());
+
+        ImageModerationRequest request = new ImageModerationRequest();
+        // 图片检测service:内容安全控制台图片增强版规则配置的serviceCode,示例:baselineCheck
+        // 支持service请参考:https://help.aliyun.com/document_detail/467826.html?0#p-23b-o19-gff
+        request.setService(serviceEnum);
+        request.setServiceParameters(JSON.toJSONString(serviceParameters));
+
+        ImageModerationResponse response = null;
+        try {
+            response = client.imageModerationWithOptions(request, runtime);
+        } catch (Exception e) {
+            throw new Exception("调用服务失败" + e.getMessage());
+        }
+        return response;
+    }
+
+    /**
+     * 批量图片检测
+     *
+     * @param imageUrl 图片地址
+     * @param serviceEnum Service类型 服务名逗号拼接
+     * @return 检测结果
+     * @throws Exception 检测异常
+     */
+    public ImageBatchModerationResponse invokeBeachFunction(String imageUrl,String serviceEnum) throws Exception {
+        Client client = createClient();
+        RuntimeOptions runtime = new RuntimeOptions();
+        Map<String, String> serviceParameters = new HashMap<>();
+        serviceParameters.put("imageUrl", imageUrl);
+        serviceParameters.put("dataId", UUID.randomUUID().toString());
+        ImageBatchModerationRequest imageBatchModerationRequest = new ImageBatchModerationRequest();
+        imageBatchModerationRequest.setService(serviceEnum);
+        imageBatchModerationRequest.setServiceParameters(JSON.toJSONString(serviceParameters));
+        ImageBatchModerationResponse response = null;
+        try {
+            response = client.imageBatchModerationWithOptions(imageBatchModerationRequest, runtime);
+        } catch (Exception e) {
+            throw new Exception("调用服务失败" + e.getMessage());
+        }
+        return response;
+    }
+    /**
+     * 发布商品场景检测
+     * 顺序调用内容治理检测、AIGC图片风险检测、图片万物识别
+     *
+     * @param imageUrl 图片地址
+     * @return 检测结果
+     * @throws Exception 检测异常
+     */
+    public ImageBatchModerationResponse productPublishCheck(String imageUrl) throws Exception {
+
+        // 批量服务key
+        String serviceEnum = ImageReviewServiceEnum.TONALITY_IMPROVE.getService() + "," + ImageReviewServiceEnum.AIGC_CHECK.getService() + "," + ImageReviewServiceEnum.GENERAL_RECOGNITION.getService();
+
+        // 批量图片检测
+        ImageBatchModerationResponse response = invokeBeachFunction(imageUrl,serviceEnum);
+        if (response != null) {
+            if (response.getStatusCode() == 200) {
+                ImageBatchModerationResponseBody body = response.getBody();
+                System.out.println("requestId=" + body.getRequestId());
+                System.out.println("code=" + body.getCode());
+                System.out.println("msg=" + body.getMsg());
+                if (body.getCode() == 200) {
+                    ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyData data = body.getData();
+                    System.out.println("dataId=" + data.getDataId());
+                    List<ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyDataResult> results = data.getResult();
+                    for (ImageBatchModerationResponseBody.ImageBatchModerationResponseBodyDataResult result : results) {
+                        System.out.println("label=" + result.getLabel());
+                        System.out.println("confidence=" + result.getConfidence());
+                    }
+                } else {
+                    System.out.println("image moderation not success. code:" + body.getCode());
+                }
+            } else {
+                System.out.println("response not success. status:" + response.getStatusCode());
+            }
+        }
+        return response;
+    }
+
+    /**
+     * 聊一聊场景检测
+     * 顺序调用图片万物识别、内容治理检测
+     *
+     * @param imageUrl 图片地址
+     * @return 检测结果
+     * @throws Exception 检测异常
+     */
+    public ImageBatchModerationResponse chatCheck(String imageUrl) throws Exception {
+        // 批量服务key
+        String serviceEnum = ImageReviewServiceEnum.GENERAL_RECOGNITION.getService() + "," + ImageReviewServiceEnum.TONALITY_IMPROVE.getService();
+
+        // 批量图片检测
+        ImageBatchModerationResponse response = invokeBeachFunction(imageUrl,serviceEnum);
+
+        return response;
+    }
+}

+ 56 - 0
alien-util/src/main/java/shop/alien/util/common/safe/ImageReviewServiceEnum.java

@@ -0,0 +1,56 @@
+package shop.alien.util.common.safe;
+
+/**
+ * 图片审核服务枚举
+ */
+public enum ImageReviewServiceEnum {
+
+    BASELINE_CHECK("baselineCheck", "通用基线检测", "检测图片中是否存在色情、涉政、暴恐、违禁等红线类的违规内容。", "通用场景"),
+    BASELINE_CHECK_PRO("baselineCheck_pro", "通用基线检测_专业版", "在通用基线检测的基础上支持更细粒度的标签返回。", "通用场景"),
+    TONALITY_IMPROVE("tonalityImprove", "内容治理检测", "检测图片中是否存在广告引流、不良引导、辱骂等影响平台秩序、内容调性或影响用户体验的内容。", "通用场景"),
+    PROFILE_PHOTO_CHECK("profilePhotoCheck", "头像图片检测", "检测头像中是否存在违规、不宜传播或者影响平台秩序的内容。建议对头像场景的图片均进行该项检测。", "业务场景"),
+    POST_IMAGE_CHECK("postImageCheck", "帖子评论图片检测", "检测帖子中图片或者评论中图片是否存在违规、不宜传播或者影响平台秩序的内容。建议对贴图评论场景的图片均进行该项检测。", "业务场景"),
+    AIGC_CHECK("aigcCheck", "AIGC图片风险检测", "针对AIGC场景,检测AIGC生成的图片是否存在违规或者不宜传播的内容。建议AIGC生成的图片都进行该项检测。", "AIGC场景"),
+    AIGC_DETECTOR("aigcDetector", "AIGC图片生成判定", "针对各种场景,判断图片是否由AIGC生成。建议需要对图片的来源进行标识时使用。", "AIGC场景"),
+    AIGC_DETECTOR_PRO("aigcDetector_pro", "AIGC图片生成判定_专业版", "在判断图片是否由AIGC生成的基础上,增加判断图片是否疑似合成,是否有PS痕迹的检测能力。", "AIGC场景"),
+    AIGC_VIOLATION_DETECTION("aigcViolationDetection", "AIGC图片侵权检测", "针对AIGC场景,检测AIGC生成的图片是否存在侵权风险。建议AIGC生成的用于素材、宣传类的图片都进行该项检测。", "AIGC场景"),
+    ADVERTISING_CHECK("advertisingCheck", "营销素材检测", "针对有推广含义的图片(包括商品图、详情介绍页、投放营销的素材等)进行专门优化,检测是否有违反广告法以及其他违规或不宜传播的内容。", "业务场景"),
+    LIVE_STREAM_CHECK("liveStreamCheck", "视频\\直播截图检测", "检测视频/直播画面是否存在违规或不宜传播的内容。建议对涉及开放公网访问的视频/直播画面均可截图进行该项检测。", "业务场景"),
+    POST_IMAGE_CHECK_BY_VL("postImageCheckByVL", "大小模型融合图片审核服务", "综合应用图片审核大模型和专家模型能力,能够全方位识别图片中的色情、性感、涉政、暴恐、违禁、宗教、引流广告、不良等违规内容。", "通用场景"),
+    BASELINE_CHECK_BY_VL("baselineCheckByVL", "通用图片审核大模型服务", "基于图片审核场景定制训练的审核大模型,能够识别图片中的涉黄、涉政、暴恐、违禁、不良、辱骂、广告等风险。支持返回大模型的原始结果。", "通用场景"),
+    OSS_BASELINE_CHECK("oss_baselineCheck", "OSS基线检测(OSS普惠版专用)", "适用于OSS检测图片中是否存在违规或不宜传播的内容,包含对黑产类图片识别能力。", "通用场景"),
+    BAILIAN_QUERY_IMAGE_CHECK("bailianQueryImageCheck", "百炼输入图片检测", "百炼图片输入场景专用,检测图片中是否存在色情、性感、涉政、暴恐、违禁、宗教、广告引流、特殊标识、行为、特定物体、不良等违规内容。", "百炼场景"),
+    BAILIAN_RESPONSE_IMAGE_CHECK("bailianResponseImageCheck", "百炼生成图片检测", "百炼图片输出场景专用,检测图片中是否存在色情、性感、涉政、暴恐、违禁、宗教、广告引流、特殊标识、行为、特定物体、不良等违规内容。", "百炼场景"),
+    GENERAL_RECOGNITION("generalRecognition", "图片万物识别", "基于大模型能力,能识别图片中的多种元素并返回元素标签和置信度。", "特殊场景"),
+    IMG_QUERY_SECURITY_CHECK("img_query_security_check", "cts.pictureReviews.ruleConfig.service.img_query_security_check", "cts.pictureReviews.ruleConfig.service.description.img_query_security_check", "--"),
+    IMG_RESPONSE_SECURITY_CHECK("img_response_security_check", "cts.pictureReviews.ruleConfig.service.img_response_security_check", "cts.pictureReviews.ruleConfig.service.description.img_response_security_check", "--"),
+    RISK_DETECTION("riskDetection", "恶意图片检测", "检测图片中隐藏的视频、播放器等风险内容。建议在存储图片和CDN流量发现异常,疑似被黑产攻击时调用。", "特殊场景");
+
+    private final String service;
+    private final String serviceName;
+    private final String serviceDescription;
+    private final String serviceScene;
+
+    ImageReviewServiceEnum(String service, String serviceName, String serviceDescription, String serviceScene) {
+        this.service = service;
+        this.serviceName = serviceName;
+        this.serviceDescription = serviceDescription;
+        this.serviceScene = serviceScene;
+    }
+
+    public String getService() {
+        return service;
+    }
+
+    public String getServiceName() {
+        return serviceName;
+    }
+
+    public String getServiceDescription() {
+        return serviceDescription;
+    }
+
+    public String getServiceScene() {
+        return serviceScene;
+    }
+}

+ 23 - 0
alien-util/src/main/java/shop/alien/util/common/safe/TextModerationResultVO.java

@@ -0,0 +1,23 @@
+package shop.alien.util.common.safe;
+
+import lombok.Data;
+
+/**
+ * 文本审核结果返回值对象
+ */
+@Data
+public class TextModerationResultVO {
+    private Integer code;
+    private String message;
+    
+    // 以下字段对应原始data对象中的属性
+    private String labels; // 标签
+    private String reason; // 原因(JSON字符串)
+
+    // 扁平化的风险信息字段
+    private String riskLevel; // 风险等级
+    private String riskTips; // 细分标签
+    private String riskWords; // 命中风险内容
+    private String customizedWords; // 命中用户词
+    private String customizedLibs; // 命中用户词库名
+}

+ 170 - 0
alien-util/src/main/java/shop/alien/util/common/safe/TextModerationUtil.java

@@ -0,0 +1,170 @@
+package shop.alien.util.common.safe;
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONObject;
+import com.aliyun.green20220302.Client;
+import com.aliyun.green20220302.models.ImageModerationResponse;
+import com.aliyun.green20220302.models.TextModerationPlusRequest;
+import com.aliyun.green20220302.models.TextModerationPlusResponse;
+import com.aliyun.green20220302.models.TextModerationPlusResponseBody;
+import com.aliyun.teaopenapi.models.Config;
+import org.springframework.beans.factory.annotation.Value;
+
+public class TextModerationUtil {
+
+
+    @Value("${ali.yundun.accessKeyID}")
+    private String accessKeyId;
+
+    @Value("${ali.yundun.secret}")
+    private String accessKeySecret;
+
+    @Value("${ali.yundun.textEndpoint}")
+    private String textEndpoint;
+
+    @Value("${ali.yundun.regionId}")
+    private String regionId;
+
+    /**
+     * 创建请求客户端
+     * @return  Client
+     * @throws Exception 创建客户端异常
+     */
+    public Client createClient() throws Exception {
+        Config config = new Config();
+        config.setAccessKeyId(accessKeyId);
+        config.setAccessKeySecret(accessKeySecret);
+        //接入区域和地址请根据实际情况修改
+        config.setRegionId(regionId);
+        config.setEndpoint(textEndpoint);
+        //读取时超时时间,单位毫秒(ms)。
+        config.setReadTimeout(6000);
+        //连接时超时时间,单位毫秒(ms)。
+        config.setConnectTimeout(3000);
+        //设置http代理。
+        //config.setHttpProxy("http://xx.xx.xx.xx:xxxx");
+        //设置https代理。
+        //config.setHttpsProxy("https://xx.xx.xx.xx:xxxx");
+        return new Client(config);
+    }
+
+    /**
+     * 根据业务类型执行文本审核
+     * @param text 待审核文本
+     * @param services 文本审核服务枚举
+     * @return 审核结果VO
+     * @throws Exception 调用服务异常
+     */
+    public TextModerationResultVO invokeFunction(String text, ImageReviewServiceEnum... services) throws Exception {
+        if (services == null || services.length == 0) {
+            throw new IllegalArgumentException("至少需要一个审核服务");
+        }
+
+        Client client = createClient();
+        
+        TextModerationResultVO resultVO = new TextModerationResultVO();
+        
+        // 存储风险等级和原因的字符串
+        StringBuilder riskTipsBuilder = new StringBuilder();
+        StringBuilder riskWordsBuilder = new StringBuilder();
+        StringBuilder customizedWordsBuilder = new StringBuilder();
+        StringBuilder customizedLibsBuilder = new StringBuilder();
+        String highestRiskLevel = "low"; // 默认最低风险等级
+        
+        try {
+            for (ImageReviewServiceEnum service : services) {
+                TextModerationPlusRequest textModerationPlusRequest = new TextModerationPlusRequest();
+                textModerationPlusRequest.setService(service.getService());
+                
+                // 构建服务参数
+                textModerationPlusRequest.setServiceParameters(buildServiceParameters(text));
+                
+                TextModerationPlusResponse response = client.textModerationPlus(textModerationPlusRequest);
+                if (response.getStatusCode() == 200) {
+                    TextModerationPlusResponseBody result = response.getBody();
+                    
+                    if (200 == result.getCode()) {
+                        // 解析审核结果
+                        TextModerationPlusResponseBody.TextModerationPlusResponseBodyData data = result.getData();
+
+                        // 解析审核结果
+                        JSONObject dataJson = JSON.parseObject(JSON.toJSONString(result.getData()));
+                        String labels = dataJson.getString("labels");
+                        String reason = dataJson.getString("reason");
+
+                        // 解析风险等级和详细信息
+                        JSONObject reasonJson = JSON.parseObject(reason);
+                        String riskLevel = reasonJson.getString("riskLevel");
+                        String riskTip = reasonJson.getString("riskTips");
+                        String riskWord = reasonJson.getString("riskWords");
+                        String customizedWord = reasonJson.getString("customizedWords");
+                        String customizedLib = reasonJson.getString("customizedLibs");
+                        
+                        // 如果存在风险信息,则添加到构建器中
+                        if (riskTip != null && !riskTip.isEmpty()) {
+                            if (riskTipsBuilder.length() > 0) {
+                                riskTipsBuilder.append(", ");
+                            }
+                            riskTipsBuilder.append(riskTip);
+                        }
+                        
+                        if (riskWord != null && !riskWord.isEmpty()) {
+                            if (riskWordsBuilder.length() > 0) {
+                                riskWordsBuilder.append(", ");
+                            }
+                            riskWordsBuilder.append(riskWord);
+                        }
+                        
+                        if (customizedWord != null && !customizedWord.isEmpty()) {
+                            if (customizedWordsBuilder.length() > 0) {
+                                customizedWordsBuilder.append(", ");
+                            }
+                            customizedWordsBuilder.append(customizedWord);
+                        }
+                        
+                        if (customizedLib != null && !customizedLib.isEmpty()) {
+                            if (customizedLibsBuilder.length() > 0) {
+                                customizedLibsBuilder.append(", ");
+                            }
+                            customizedLibsBuilder.append(customizedLib);
+                        }
+                        
+                        // 判断风险等级优先级
+                        if (riskLevel != null) {
+                            if (riskLevel.equals("high") && !highestRiskLevel.equals("high")) {
+                                highestRiskLevel = "high";
+                            } else if (riskLevel.equals("medium") && highestRiskLevel.equals("low")) {
+                                highestRiskLevel = "medium";
+                            }
+                        }
+                        
+                        // 设置基础信息
+                        resultVO.setLabels(labels);
+                    }
+                }
+            }
+            
+            // 设置结果VO
+            resultVO.setCode(200);
+            resultVO.setMessage("OK");
+            resultVO.setRiskLevel(highestRiskLevel);
+            resultVO.setRiskTips(riskTipsBuilder.toString());
+            resultVO.setRiskWords(riskWordsBuilder.toString());
+            resultVO.setCustomizedWords(customizedWordsBuilder.toString());
+            resultVO.setCustomizedLibs(customizedLibsBuilder.toString());
+            
+        } catch (Exception e) {
+            resultVO.setCode(500);
+            resultVO.setMessage("调用服务失败: " + e.getMessage());
+        }
+        
+        return resultVO;
+    }
+
+
+    private String buildServiceParameters(String text) {
+        // 创建服务参数JSON
+        JSONObject serviceParameters = new JSONObject();
+        serviceParameters.put("content", text);
+        return serviceParameters.toJSONString();
+    }
+}

+ 26 - 0
alien-util/src/main/java/shop/alien/util/common/safe/TextReviewServiceEnum.java

@@ -0,0 +1,26 @@
+package shop.alien.util.common.safe;
+
+import jdk.nashorn.internal.runtime.logging.Logger;
+import lombok.Getter;
+
+/**
+ * @author Alien
+ * @date 2021/09/05
+ */
+@Getter
+@Logger
+public enum TextReviewServiceEnum {
+    SPAM("spam"),
+    AD("ad"),
+    POLITICS("politics"),
+    ABUSE("abuse"),
+    VIOLENCE("violence"),
+    PORNOGRAPHY("pornography");
+
+    private final String service;
+
+    TextReviewServiceEnum(String service) {
+        this.service = service;
+    }
+
+}