diff --git a/pom.xml b/pom.xml index 31b7f8c4b..153629dc1 100644 --- a/pom.xml +++ b/pom.xml @@ -298,6 +298,14 @@ + + com.tencentcloudapi + tencentcloud-sdk-java + + + 3.1.1000 + + diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java index ad669aab8..adcd53a85 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysLoginController.java @@ -23,7 +23,7 @@ import com.ruoyi.system.service.ISysMenuService; import com.ruoyi.system.service.ISysRoleService; import com.ruoyi.system.service.ISysUserService; import com.ruoyi.web.controller.system.vo.*; -import com.ruoyi.xkt.manager.AliAuthManager; +import com.ruoyi.xkt.manager.TencentAuthManager; import com.ruoyi.xkt.service.IStoreService; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; @@ -62,7 +62,7 @@ public class SysLoginController { @Autowired private RedisCache redisCache; @Autowired - private AliAuthManager aliAuthManager; + private TencentAuthManager tencentAuthManager; @Autowired private SysPasswordService passwordService; @@ -75,8 +75,7 @@ public class SysLoginController { @ApiOperation(value = "用户名密码登录") @PostMapping("/loginByUname") public AjaxResult login(@Validated @RequestBody LoginByUsernameVO loginBody) { - boolean captchaPass = aliAuthManager.validate(loginBody.getLot_number(), loginBody.getCaptcha_output(), - loginBody.getPass_token(), loginBody.getGen_time()); + boolean captchaPass = tencentAuthManager.validate(loginBody.getTicket(), loginBody.getRandstr()); if (!captchaPass) { return AjaxResult.error("验证失败"); } @@ -110,8 +109,7 @@ public class SysLoginController { @ApiOperation(value = "发送登录短信验证码") @PostMapping("/sendSmsVerificationCode") public R sendSmsVerificationCode(@Validated @RequestBody LoginSmsReqVO vo) { - boolean captchaPass = aliAuthManager.validate(vo.getLot_number(), vo.getCaptcha_output(), - vo.getPass_token(), vo.getGen_time()); + boolean captchaPass = tencentAuthManager.validate(vo.getTicket(), vo.getRandstr()); if (!captchaPass) { return R.fail("验证失败"); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java index 43a091d09..10398fdb2 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/SysRegisterController.java @@ -16,7 +16,7 @@ import com.ruoyi.system.service.ISysUserService; import com.ruoyi.web.controller.system.vo.LoginSmsReqVO; import com.ruoyi.web.controller.system.vo.RegisterBySmsCodeVO; import com.ruoyi.web.controller.xkt.vo.PhoneNumberVO; -import com.ruoyi.xkt.manager.AliAuthManager; +import com.ruoyi.xkt.manager.TencentAuthManager; import io.swagger.annotations.Api; import io.swagger.annotations.ApiOperation; import org.springframework.beans.factory.annotation.Autowired; @@ -48,7 +48,7 @@ public class SysRegisterController extends BaseController { private ISysUserService userService; @Autowired - private AliAuthManager aliAuthManager; + private TencentAuthManager tencentAuthManager; @ApiOperation(value = "档口供应商注册") @PostMapping("/registerStore") @@ -95,8 +95,7 @@ public class SysRegisterController extends BaseController { @ApiOperation(value = "发送注册短信验证码") @PostMapping("/sendSmsVerificationCode") public R sendSmsVerificationCode(@Validated @RequestBody LoginSmsReqVO vo) { - boolean captchaPass = aliAuthManager.validate(vo.getLot_number(), vo.getCaptcha_output(), - vo.getPass_token(), vo.getGen_time()); + boolean captchaPass = tencentAuthManager.validate(vo.getTicket(), vo.getRandstr()); if (!captchaPass) { return R.fail("验证失败"); } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginByUsernameVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginByUsernameVO.java index c5857bf4a..cff68d706 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginByUsernameVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginByUsernameVO.java @@ -1,6 +1,6 @@ package com.ruoyi.web.controller.system.vo; -import com.ruoyi.web.controller.xkt.vo.AliCaptchaAuthReqVO; +import com.ruoyi.web.controller.xkt.vo.TencentCaptchaAuthReqVO; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -17,7 +17,7 @@ import javax.validation.constraints.NotEmpty; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class LoginByUsernameVO extends AliCaptchaAuthReqVO { +public class LoginByUsernameVO extends TencentCaptchaAuthReqVO { /** * 用户名 */ diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginSmsReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginSmsReqVO.java index 2f1be3930..b1aae905e 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginSmsReqVO.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/vo/LoginSmsReqVO.java @@ -1,6 +1,6 @@ package com.ruoyi.web.controller.system.vo; -import com.ruoyi.web.controller.xkt.vo.AliCaptchaAuthReqVO; +import com.ruoyi.web.controller.xkt.vo.TencentCaptchaAuthReqVO; import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import lombok.Data; @@ -18,7 +18,7 @@ import javax.validation.constraints.Pattern; @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class LoginSmsReqVO extends AliCaptchaAuthReqVO { +public class LoginSmsReqVO extends TencentCaptchaAuthReqVO { @Pattern(regexp = "^1[3-9]\\d{9}$", message = "手机号格式不正确") @NotEmpty(message = "手机号不能为空") diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/TencentCaptchaAuthReqVO.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/TencentCaptchaAuthReqVO.java new file mode 100644 index 000000000..d33a6147e --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/xkt/vo/TencentCaptchaAuthReqVO.java @@ -0,0 +1,24 @@ +package com.ruoyi.web.controller.xkt.vo; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import javax.validation.constraints.NotEmpty; + +/** + * @author liangyq + * @date 2025-07-22 + */ +@ApiModel +@Data +public class TencentCaptchaAuthReqVO { + + @NotEmpty(message = "ticket不能为空") + @ApiModelProperty("ticket(图像验证参数)") + private String ticket; + + @NotEmpty(message = "randstr不能为空") + @ApiModelProperty("randstr(图像验证参数)") + private String randstr; +} diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index f5b60debe..444281df3 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -226,3 +226,11 @@ aliauth: captcha: appId: 386ec134856c9fe7d47ce2a34ee91038 appKey: 1b4e3ff703ca1ea0fb802d188079a25c + +# 腾讯认证 +tencent: + secretId: AKIDEbxNfmkW5RaVDhDc2Pcs198zpeP6kEZi + secretKey: 3ub7QZYN9qR4bxBE6qQs9GBuSnuoW0JP + captcha: + captchaAppId: 199022475 + appSecretKey: wcqMdqjV3fnvFKxUAq5mwulnD diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index d6fc361e9..006555dd0 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -193,6 +193,11 @@ 1.16.1 + + com.tencentcloudapi + tencentcloud-sdk-java + + \ No newline at end of file diff --git a/xkt/src/main/java/com/ruoyi/xkt/manager/TencentAuthManager.java b/xkt/src/main/java/com/ruoyi/xkt/manager/TencentAuthManager.java new file mode 100644 index 000000000..5fb11c2b1 --- /dev/null +++ b/xkt/src/main/java/com/ruoyi/xkt/manager/TencentAuthManager.java @@ -0,0 +1,70 @@ +package com.ruoyi.xkt.manager; + +import com.ruoyi.common.utils.ip.IpUtils; +import com.tencentcloudapi.captcha.v20190722.CaptchaClient; +import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultRequest; +import com.tencentcloudapi.captcha.v20190722.models.DescribeCaptchaResultResponse; +import com.tencentcloudapi.common.AbstractModel; +import com.tencentcloudapi.common.Credential; +import com.tencentcloudapi.common.profile.ClientProfile; +import com.tencentcloudapi.common.profile.HttpProfile; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +/** + * @author liangyq + * @date 2025-08-06 + */ +@Slf4j +@Component +public class TencentAuthManager implements InitializingBean { + + private static final Long SUCCESS_CODE = 1L; + + @Value("${tencent.secretId:}") + private String secretId; + @Value("${tencent.secretKey:}") + private String secretKey; + @Value("${tencent.captcha.captchaAppId:}") + private Long captchaAppId; + @Value("${tencent.captcha.appSecretKey:}") + private String appSecretKey; + + private CaptchaClient client; + + @Override + public void afterPropertiesSet() throws Exception { + Credential cred = new Credential(secretId, secretKey); + // 实例化一个http选项,可选的,没有特殊需求可以跳过 + HttpProfile httpProfile = new HttpProfile(); + httpProfile.setEndpoint("captcha.tencentcloudapi.com"); + // 实例化一个client选项,可选的,没有特殊需求可以跳过 + ClientProfile clientProfile = new ClientProfile(); + clientProfile.setHttpProfile(httpProfile); + // 实例化要请求产品的client对象,clientProfile是可选的 + client = new CaptchaClient(cred, "", clientProfile); + } + + public boolean validate(String ticket, String randstr) { + try { + DescribeCaptchaResultRequest req = new DescribeCaptchaResultRequest(); + req.setCaptchaType(9L); + req.setTicket(ticket); + req.setRandstr(randstr); + req.setUserIp(IpUtils.getIpAddr()); + req.setCaptchaAppId(captchaAppId); + req.setAppSecretKey(appSecretKey); + // 返回的resp是一个DescribeCaptchaResultResponse的实例,与请求对象对应 + DescribeCaptchaResultResponse resp = client.DescribeCaptchaResult(req); + if (SUCCESS_CODE.equals(resp.getCaptchaCode())) { + return true; + } + log.warn("滑动验证未通过: {}", AbstractModel.toJsonString(resp)); + } catch (Exception e) { + log.error("滑动验证校验异常", e); + } + return false; + } +}