手机号认证

This commit is contained in:
D 2024-04-16 14:01:24 +08:00
parent 62c9824426
commit 4c085cff34
7 changed files with 309 additions and 13 deletions

View File

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

View File

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

View File

@ -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}")

View File

@ -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());
}
}
}

View File

@ -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"),

View File

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

View File

@ -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,6 +42,83 @@ 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
StringBuilder result = new StringBuilder();