diff --git a/ruoyi-oauth/ruoyi-oauth-common/src/main/java/com/ruoyi/oauth/common/enums/OauthVerificationUse.java b/ruoyi-oauth/ruoyi-oauth-common/src/main/java/com/ruoyi/oauth/common/enums/OauthVerificationUse.java new file mode 100644 index 0000000..0ac3126 --- /dev/null +++ b/ruoyi-oauth/ruoyi-oauth-common/src/main/java/com/ruoyi/oauth/common/enums/OauthVerificationUse.java @@ -0,0 +1,37 @@ +package com.ruoyi.oauth.common.enums; + +public enum OauthVerificationUse { + + LOGIN("登录", "login"), + REGISTER("注册", "register"), + DISABLE("禁用", "disable"), + RESET_PASSWORD("重置密码", "reset_password"), + RESET_PHONE("重置手机号", "reset_phone"), + Other("其他","other"); + + + + private String name; + private String value; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getValue() { + return value; + } + + public void setValue(String value) { + this.value = value; + } + + private OauthVerificationUse(String name, String value) { + this.name = name; + this.value = value; + } +} diff --git a/ruoyi-oauth/ruoyi-oauth-common/src/main/java/com/ruoyi/oauth/common/service/OauthVerificationCodeService.java b/ruoyi-oauth/ruoyi-oauth-common/src/main/java/com/ruoyi/oauth/common/service/OauthVerificationCodeService.java new file mode 100644 index 0000000..acef303 --- /dev/null +++ b/ruoyi-oauth/ruoyi-oauth-common/src/main/java/com/ruoyi/oauth/common/service/OauthVerificationCodeService.java @@ -0,0 +1,15 @@ +package com.ruoyi.oauth.common.service; + +import com.ruoyi.oauth.common.enums.OauthVerificationUse; + +/** + * code认证方式接口 + * + * @author zlh + * @date 2024-04-16 + */ +public interface OauthVerificationCodeService { + public boolean sendCode(String o, String code,OauthVerificationUse use) throws Exception; + public String checkCode(String o, String code,OauthVerificationUse use) throws Exception; + +} diff --git a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/constant/DySmsConstant.java b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/constant/DySmsConstant.java index 3a9d6d1..3c6e481 100644 --- a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/constant/DySmsConstant.java +++ b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/constant/DySmsConstant.java @@ -3,6 +3,12 @@ package com.ruoyi.oauth.phone.constant; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; +/** + * 手机号认证数据 + * + * @author Dftre + * @date 2024-04-16 + */ @Component public class DySmsConstant { @Value("${oauth.phone.dysms.appId}") diff --git a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/controller/DySmsController.java b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/controller/DySmsController.java index fb7bb5f..37da61c 100644 --- a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/controller/DySmsController.java +++ b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/controller/DySmsController.java @@ -1,24 +1,153 @@ package com.ruoyi.oauth.phone.controller; +import java.util.Random; + import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import com.ruoyi.common.annotation.Anonymous; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.LoginBody; +import com.ruoyi.common.utils.SecurityUtils; +import com.ruoyi.oauth.common.enums.OauthVerificationUse; import com.ruoyi.oauth.phone.service.DySmsService; +import com.ruoyi.system.service.ISysUserService; - +/** + * 手机号认证Controller + * + * @author zlh + * @date 2024-04-16 + */ @RestController -@Anonymous @RequestMapping("/oauth/phone") -public class DySmsController { +public class DySmsController extends BaseController { @Autowired public DySmsService dySmsService; - @PostMapping("/login") - public String postMethodName() { - dySmsService.doLogin("17854126030"); - return null; + + @Autowired + private ISysUserService userService; + + @Anonymous + @PostMapping("/sendcode/{mode}") // 发送验证码 + public AjaxResult sendcode(@RequestBody LoginBody loginBody, @PathVariable(value = "mode") String mode) + throws Exception { + try { + OauthVerificationUse oauthVerificationUse = null; + switch (mode) { + case "login": + oauthVerificationUse = OauthVerificationUse.LOGIN; + break; + case "register": + oauthVerificationUse = OauthVerificationUse.REGISTER; + break; + case "disable": + oauthVerificationUse = OauthVerificationUse.DISABLE; + break; + case "resetpassword": + oauthVerificationUse = OauthVerificationUse.RESET_PASSWORD; + break; + case "resetphone": + oauthVerificationUse = OauthVerificationUse.RESET_PHONE; + break; + default: + oauthVerificationUse = OauthVerificationUse.Other; + } + String code = generateRandomString(6); + dySmsService.sendCode(loginBody.getUsername(), code, oauthVerificationUse); + return AjaxResult.success("发送验证码成功"); + } catch (Exception e) { + return AjaxResult.error("发送验证码失败,原因: " + e.getMessage()); + } + } + + public static String generateRandomString(int n) { + String characters = "0123456789"; // ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz + StringBuilder result = new StringBuilder(); + Random random = new Random(); + + for (int i = 0; i < n; i++) { + int index = random.nextInt(characters.length()); + result.append(characters.charAt(index)); + } + + return result.toString(); + } + + @Anonymous + @PostMapping("/login") // 登录 + public AjaxResult postMethodName(@RequestBody LoginBody loginBody) throws Exception { + if (dySmsService.checkCode(loginBody.getUsername(), loginBody.getCode(), + OauthVerificationUse.LOGIN) == "false") { + return AjaxResult.error("登录失败"); + } else { + return AjaxResult.success("登录成功"); + } + } + + @Anonymous + @PostMapping("/register") // 注册 + public AjaxResult postenroll(@RequestBody LoginBody loginBody) throws Exception { + try { + dySmsService.checkCode(loginBody.getUsername(), loginBody.getCode(), OauthVerificationUse.REGISTER); + // 验证通过,执行注册逻辑 + SysUser user = new SysUser(); + user.setUserName(loginBody.getUsername()); + user.setNickName(loginBody.getUsername()); + user.setPassword(SecurityUtils.encryptPassword(loginBody.getPassword())); + user.setPhonenumber(loginBody.getUsername()); + userService.insertUser(user); + return AjaxResult.success("注册成功"); + } catch (Exception e) { + // return "注册失败,原因: " + e.getMessage(); + return AjaxResult.error("注册失败"); + } + } + + @PostMapping("/disable") // 注销 + public AjaxResult postlogout(@RequestBody LoginBody loginBody) throws Exception { + try { + dySmsService.checkCode(getUsername(), loginBody.getCode(), OauthVerificationUse.DISABLE); + // 验证通过,执行注销逻辑 + SysUser sysUser = userService.selectUserByPhone(loginBody.getUsername()); + userService.deleteUserById(sysUser.getUserId()); + return AjaxResult.success("注销成功"); + } catch (Exception e) { + return AjaxResult.error("注销失败,原因: " + e.getMessage()); + } + } + @Anonymous + @PostMapping("/resetpassword") // 重置密码 + public AjaxResult postpassword(@RequestBody LoginBody loginBody) throws Exception { + try { + dySmsService.checkCode(loginBody.getUsername(), loginBody.getCode(), OauthVerificationUse.RESET_PASSWORD); + // 验证通过,执行重置密码逻辑 + SysUser sysUser = userService.selectUserByPhone(loginBody.getUsername()); + sysUser.setPassword(SecurityUtils.encryptPassword(loginBody.getPassword())); + userService.updateUser(sysUser); + return AjaxResult.success("重置密码成功"); + } catch (Exception e) { + return AjaxResult.error("重置密码失败,原因: " + e.getMessage()); + } + } + + @PostMapping("/resetphone") // 重置手机号 + public AjaxResult postphone(@RequestBody LoginBody loginBody) throws Exception { + try { + dySmsService.checkCode(loginBody.getUsername(), loginBody.getCode(), OauthVerificationUse.RESET_PHONE); + // 验证通过,执行重置密码逻辑 + SysUser sysUser = userService.selectUserByUserName(getUsername()); + sysUser.setPhonenumber(loginBody.getUsername()); + userService.updateUser(sysUser); + return AjaxResult.success("重置手机号成功"); + } catch (Exception e) { + return AjaxResult.error("重置手机号失败,原因: " + e.getMessage()); + } } - } diff --git a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/enums/DySmsTemplate.java b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/enums/DySmsTemplate.java index 6168379..7036ec5 100644 --- a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/enums/DySmsTemplate.java +++ b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/enums/DySmsTemplate.java @@ -2,6 +2,12 @@ package com.ruoyi.oauth.phone.enums; import com.ruoyi.common.utils.StringUtils; +/** + * 手机号认证短信模板 + * + * @author Dftre + * @date 2024-04-16 + */ public enum DySmsTemplate { /** 登录短信模板编码 */ LOGIN_TEMPLATE_CODE("SMS_175435174", "Ruoyi", "code"), diff --git a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/service/DySmsService.java b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/service/DySmsService.java index a3dd993..17d3943 100644 --- a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/service/DySmsService.java +++ b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/service/DySmsService.java @@ -1,5 +1,21 @@ package com.ruoyi.oauth.phone.service; +import com.ruoyi.oauth.common.enums.OauthVerificationUse; + +/** + * 手机号认证Servcie + * + * @author zlh + * @date 2024-04-16 + */ public interface DySmsService { public String doLogin(String phone); + + public boolean sendCode(String phone, String code, OauthVerificationUse use) throws Exception; + + public String checkCode(String phone, String code, OauthVerificationUse use) throws Exception; + +// public String doenroll(String phone,String username, String password); + + } diff --git a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/service/Impl/DySmsServiceImpl.java b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/service/Impl/DySmsServiceImpl.java index 413338e..76ce849 100644 --- a/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/service/Impl/DySmsServiceImpl.java +++ b/ruoyi-oauth/ruoyi-oauth-phone/src/main/java/com/ruoyi/oauth/phone/service/Impl/DySmsServiceImpl.java @@ -3,6 +3,8 @@ package com.ruoyi.oauth.phone.service.Impl; import java.util.Random; import java.util.concurrent.TimeUnit; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -13,13 +15,21 @@ import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.framework.web.service.TokenService; import com.ruoyi.framework.web.service.UserDetailsServiceImpl; +import com.ruoyi.oauth.common.enums.OauthVerificationUse; +import com.ruoyi.oauth.common.service.OauthVerificationCodeService; import com.ruoyi.oauth.phone.enums.DySmsTemplate; import com.ruoyi.oauth.phone.service.DySmsService; import com.ruoyi.oauth.phone.utils.DySmsUtil; import com.ruoyi.system.service.ISysUserService; +/** + * 手机号认证Servcie + * + * @author zlh + * @date 2024-04-16 + */ @Service -public class DySmsServiceImpl implements DySmsService { +public class DySmsServiceImpl implements DySmsService, OauthVerificationCodeService { @Autowired private DySmsUtil dySmsUtil; @@ -32,8 +42,85 @@ public class DySmsServiceImpl implements DySmsService { @Autowired private TokenService tokenService; + private static final Logger log = LoggerFactory.getLogger(DySmsServiceImpl.class); + + + public boolean beforeSendCode(String phone, OauthVerificationUse use) throws Exception {//1.查验手机号是否存在,分辨登录和删除用户以及注册用户 + boolean havePhoneFlag= userService.selectUserByPhone(phone) != null; + if((use.equals(OauthVerificationUse.LOGIN ) || use.equals(OauthVerificationUse.DISABLE )||use.equals(OauthVerificationUse.RESET_PASSWORD) )&& !havePhoneFlag){ + throw new ServiceException("该手机号未绑定用户"); + }else if((use.equals(OauthVerificationUse.REGISTER ) ||use.equals(OauthVerificationUse.RESET_PHONE))&& havePhoneFlag){ + throw new ServiceException("该手机号已绑定用户"); + } + return true; + } + + @Override + public boolean sendCode(String phone, String code, OauthVerificationUse use) throws Exception {//1.查验手机号是否存在,分辨登录和删除用户以及注册用户 + //限制短信一分钟只能发送一次短信 + String cacheKey = "phone_codes_" + use.getValue() + "_" + phone; + if(redisCache.hasKey(cacheKey)){ + throw new ServiceException("请在1分钟后再发送短信"); + } + + try { + JSONObject templateParams = new JSONObject(); + templateParams.put("code", code); + dySmsUtil.sendSms(DySmsTemplate.Test_TEMPLATE_CODE, templateParams, phone); + redisCache.setCacheObject("phone_codes_" + use.getValue() + "_" + phone, code, 1, TimeUnit.MINUTES); + log.info("发送手机验证码成功:{ phone: " + phone + " code:" + code + "}"); + return true; + } catch (Exception e) { + log.error("发送手机验证码异常:" + phone); + throw e; + } + } + + + @Override + public String checkCode(String phone, String code, OauthVerificationUse use) throws Exception{ + String cacheKey = "phone_codes_" + use.getValue() + "_" + phone; + String cachedCode = redisCache.getCacheObject(cacheKey); // 从缓存中获取验证码 + boolean havePhoneFlag= userService.selectUserByPhone(phone) != null; + if(use.equals(OauthVerificationUse.LOGIN ) && havePhoneFlag){//登录校验 + if (code.equals(cachedCode)) { + SysUser sysUser = userService.selectUserByPhone(phone); + LoginUser loginUser = (LoginUser) userDetailsServiceImpl.createLoginUser(sysUser); + return tokenService.createToken(loginUser); +// return true; + } else { + throw new ServiceException("验证码错误"); + } + }else if(use.equals(OauthVerificationUse.REGISTER )&& !havePhoneFlag){//注册校验 + if (code.equals(cachedCode)) { + return Boolean.toString(true); + } else { + throw new ServiceException("验证码错误"); + } + }else if(use.equals(OauthVerificationUse.DISABLE )&& havePhoneFlag){//注销校验 + if (code.equals(cachedCode)) { + return Boolean.toString(true); + } else { + throw new ServiceException("验证码错误"); + } + }else if(use.equals(OauthVerificationUse.RESET_PASSWORD )&& havePhoneFlag){//重置密码校验 + if (code.equals(cachedCode)) { + return Boolean.toString(true); + } else { + throw new ServiceException("验证码错误"); + } + }else if(use.equals(OauthVerificationUse.RESET_PHONE )&& !havePhoneFlag){//重置账号校验 + if (code.equals(cachedCode)) { + return Boolean.toString(true); + } else { + throw new ServiceException("验证码错误"); + } + } + return Boolean.toString(false); + } + public static String generateRandomString(int n) { - String characters = "0123456789"; //ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz + String characters = "0123456789"; // ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz StringBuilder result = new StringBuilder(); Random random = new Random(); @@ -48,7 +135,7 @@ public class DySmsServiceImpl implements DySmsService { @Override public String doLogin(String phone) { String verify = redisCache.getCacheObject("phone_codes_login" + phone); - if(verify != null){ + if (verify != null) { throw new ServiceException("该手机号验证码未过期"); } String code = generateRandomString(6); @@ -82,9 +169,9 @@ public class DySmsServiceImpl implements DySmsService { String code = generateRandomString(6); redisCache.setCacheObject("phone_codes_register" + phone, code, 1, TimeUnit.MINUTES); String verify = redisCache.getCacheObject("phone_codes_register" + phone); - if(verify != null){ + if (verify != null) { throw new ServiceException("该手机号验证码未过期"); - }else{ + } else { try { dySmsUtil.sendSms(null, null, phone); redisCache.setCacheObject("phone_codes_register" + phone, code, 1, TimeUnit.MINUTES);