zoujiajian 2 лет назад
Родитель
Сommit
5ac4416a38

+ 6 - 0
netflix-common/pom.xml

@@ -104,6 +104,12 @@
             <artifactId>tencentcloud-sdk-java-faceid</artifactId>
             <version>3.1.694</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.tencentcloudapi</groupId>
+            <artifactId>tencentcloud-sdk-java</artifactId>
+            <version>3.1.830</version>
+        </dependency>
     </dependencies>
 
 

+ 46 - 0
netflix-common/src/main/java/com/cyksj/common/util/SmsUtil.java

@@ -4,6 +4,9 @@ import cn.hutool.http.HttpRequest;
 import cn.hutool.http.HttpResponse;
 import cn.hutool.http.Method;
 import cn.hutool.json.JSONObject;
+import com.tencentcloudapi.captcha.v20190722.CaptchaClient;
+import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest;
+import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultResponse;
 import com.tencentcloudapi.common.Credential;
 import com.tencentcloudapi.common.exception.TencentCloudSDKException;
 import com.tencentcloudapi.common.profile.ClientProfile;
@@ -48,6 +51,12 @@ public class SmsUtil {
     //账号修改密码国际短信通知
     private static final String TENCENT_SMS_ACCOUNT_INTERNATIONAL_TEMPLATE_ID = "2040574";
 
+    //腾讯云图形认证密钥id
+    private static final Long TENCENT_SMS_CODE_AUTH_APP_ID = 197694921l;
+
+    //腾讯云图形认证密钥key
+    private static final String TENCENT_SMS_CODE_AUTH_SECRET_KEY = "vOd32NejzMM2HQX0WtKy7ItvK";
+
     private static final Logger log = LoggerFactory.getLogger(SmsUtil.class);
 
     public static void main(String[] args) {
@@ -193,4 +202,41 @@ public class SmsUtil {
         }
         return false;
     }
+
+    public static void checkTencentCaptcha(String ticket, String userIp,String randsStr) {
+        try {
+            // 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
+            // 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
+            // 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
+            Credential cred = new Credential(TENCENT_SMS_SECRET_ID, TENCENT_SMS_SECRET_KEY);
+            // 实例化一个http选项,可选的,没有特殊需求可以跳过
+            HttpProfile httpProfile = new HttpProfile();
+            // 推荐使用北极星,相关指引可访问如下链接
+            // https://git.woa.com/tencentcloud-internal/tencentcloud-sdk-java#%E5%8C%97%E6%9E%81%E6%98%9F
+            httpProfile.setEndpoint("captcha.tencentcloudapi.com");
+            // 实例化一个client选项,可选的,没有特殊需求可以跳过
+            ClientProfile clientProfile = new ClientProfile();
+            clientProfile.setHttpProfile(httpProfile);
+            // 实例化要请求产品的client对象,clientProfile是可选的
+            CaptchaClient client = new CaptchaClient(cred, "", clientProfile);
+            // 实例化一个请求对象,每个接口都会对应一个request对象
+            DescribeCaptchaResultRequest req = new DescribeCaptchaResultRequest();
+            req.setCaptchaType(9L);
+            req.setTicket(ticket);
+            req.setUserIp(userIp);
+            req.setRandstr(randsStr);
+            req.setCaptchaAppId(TENCENT_SMS_CODE_AUTH_APP_ID);
+            req.setAppSecretKey(TENCENT_SMS_CODE_AUTH_SECRET_KEY);
+
+            // 返回的resp是一个DescribeCaptchaResultResponse的实例,与请求对象对应
+            DescribeCaptchaResultResponse resp = client.DescribeCaptchaResult(req);
+            //1 OK 验证通过
+            Long captchaCode = resp.getCaptchaCode();
+            if (captchaCode != 0) {
+                log.error("腾讯云图形验证错误:{}", resp.getCaptchaMsg());
+            }
+        } catch (TencentCloudSDKException e) {
+            log.error("腾讯云图形认证异常:{}", StringUtil.getErrorText(e));
+        }
+    }
 }

+ 1 - 1
netflix-service/src/main/java/com/cyksj/service/user/BadIntentionOpService.java

@@ -3,7 +3,7 @@ package com.cyksj.service.user;
 import javax.servlet.http.HttpServletRequest;
 
 public interface BadIntentionOpService {
-    void checkHandleBadUserOp(String phone, String verifyCode);
+    void checkHandleBadUserOp(String phone, String verifyCode, String ticket, String randStr, HttpServletRequest request);
 
     void isBadOpLoginPhone(HttpServletRequest request, String phone);
 }

+ 22 - 14
netflix-service/src/main/java/com/cyksj/service/user/impl/BadIntentionOpServiceImpl.java

@@ -1,15 +1,16 @@
 package com.cyksj.service.user.impl;
 
+import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.extra.servlet.ServletUtil;
 import cn.hutool.http.HttpUtil;
 import cn.hutool.json.JSONObject;
 import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.SmsUtil;
 import com.cyksj.common.util.StringUtil;
 import com.cyksj.redis.RedisService;
 import com.cyksj.service.user.BadIntentionOpService;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.commons.lang3.StringUtils;
 import org.springframework.beans.factory.annotation.Value;
 import org.springframework.stereotype.Service;
 
@@ -38,23 +39,30 @@ public class BadIntentionOpServiceImpl implements BadIntentionOpService {
     private static final String VERIFY_URL =  "https://captcha.luosimao.com/api/site_verify";
 
     @Override
-    public void checkHandleBadUserOp(String phone, String verifyCode) {
+    public void checkHandleBadUserOp(String phone, String verifyCode, String ticket, String randStr, HttpServletRequest request) {
         if ("13662979985".equals(phone)) {
             throw BusinessRuntimeException.getInstance("异常手机号");
         }
-        if (StringUtils.isBlank(verifyCode)) {
-            throw BusinessRuntimeException.getInstance("人机校验不通过");
+//        if (StringUtils.isBlank(verifyCode)) {
+//            throw BusinessRuntimeException.getInstance("人机校验不通过");
+//        } else {
+//            //银河官网
+//            JSONObject res = checkVerifyCode(apiKey, verifyCode);
+//            if (!res.getStr("res").equals("success")) {
+//                //小店域名
+//                res = checkVerifyCode(shoppingApikey, verifyCode);
+//                if (!res.getStr("res").equals("success")) {
+//                    log.error("手机号:{}验证码校验不通过 res:{}", phone, res);
+//                    throw BusinessRuntimeException.getInstance("人机校验不通过");
+//                }
+//            }
+//        }
+        if (ObjectUtil.hasEmpty(ticket, randStr)) {
+            throw BusinessRuntimeException.getInstance("请先完成图形认证");
         } else {
-            //银河官网
-            JSONObject res = checkVerifyCode(apiKey, verifyCode);
-            if (!res.getStr("res").equals("success")) {
-                //小店域名
-                res = checkVerifyCode(shoppingApikey, verifyCode);
-                if (!res.getStr("res").equals("success")) {
-                    log.error("手机号:{}验证码校验不通过 res:{}", phone, res);
-                    throw BusinessRuntimeException.getInstance("人机校验不通过");
-                }
-            }
+            //腾讯云图形验证
+            String ip = StringUtil.getInternalAddressByIP(ServletUtil.getClientIP(request));
+            SmsUtil.checkTencentCaptcha(ticket, ip, randStr);
         }
         String dayKey = RedisService.key.PHONE_CODE_USER_NUM_KEY_DAY.getName() + phone;
         if (redisService.hasKey(RedisService.key.PHONE_CODE_BALCK_KEY.getName() + phone)) {

+ 2 - 2
netflix-web/src/main/java/com/cyksj/web/controller/user/AuthorizationController.java

@@ -365,7 +365,7 @@ public class AuthorizationController {
      */
     @GetMapping("/get/phone/code")
     @NoSubmit
-    public Result<String> getPhoneCode(String phone, Integer digit, @RequestParam(defaultValue = "0") Boolean isFree, Integer cid, String verifyCode) throws Exception {
+    public Result<String> getPhoneCode(String phone, Integer digit, @RequestParam(defaultValue = "0") Boolean isFree, Integer cid, String verifyCode, String ticket,String randStr) throws Exception {
         if (cid == null) cid = 86;
         if (StrUtil.isBlank(phone) || (86 == cid && !Validator.isMobile(phone))) {
             throw BusinessRuntimeException.getInstance("请输入正确的手机号");
@@ -379,7 +379,7 @@ public class AuthorizationController {
             throw BusinessRuntimeException.getInstance("短信验证码未失效");
         }
         //是否是恶意用户
-        badIntentionOpService.checkHandleBadUserOp(phone, verifyCode);
+        badIntentionOpService.checkHandleBadUserOp(phone, verifyCode, ticket, randStr, request);
         String code = StringUtil.getRandomCodeStr(digit);
         Boolean isFlag;
         if (!isFree) {