验证码登陆/密码登陆/短信发送

This commit is contained in:
kuang.yife 2023-12-10 14:17:38 +08:00
parent 5b9ea18698
commit 09ad8e33fe
16 changed files with 383 additions and 10 deletions

21
pom.xml
View File

@ -33,12 +33,33 @@
<velocity.version>2.3</velocity.version>
<hutool.version>5.8.22</hutool.version>
<knife4j.version>3.0.3</knife4j.version>
<ali-sdk.version>4.5.3</ali-sdk.version>
<ali-sms.version>2.0.1</ali-sms.version>
<ali-oss.version>3.10.2</ali-oss.version>
</properties>
<!-- 依赖声明 -->
<dependencyManagement>
<dependencies>
<!--阿里云核心API-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>${ali-sdk.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>${ali-sms.version}</version>
</dependency>
<!--阿里云oss存储API-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
<version>${ali-oss.version}</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>

View File

@ -17,6 +17,21 @@
<dependencies>
<!--阿里云核心API-->
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
</dependency>
<!--阿里云oss存储API-->
<dependency>
<groupId>com.aliyun.oss</groupId>
<artifactId>aliyun-sdk-oss</artifactId>
</dependency>
<!-- SpringBoot集成thymeleaf模板 -->
<dependency>
<groupId>org.springframework.boot</groupId>

View File

@ -3,27 +3,54 @@ package com.ruoyi.web.controller.app;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.web.request.LoginReq;
import com.ruoyi.web.response.LoginResp;
import com.ruoyi.web.service.LoginService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.validation.constraints.NotNull;
/**
* <p>登陆相关接口</p>
* @author clunt
*/
@Api(value = "App*登陆接口")
@Api(tags = "App*登陆接口")
@RestController
@RequestMapping(value = "/app/login")
public class LoginController {
@Autowired
private LoginService loginService;
//密码登陆
@ResponseBody
@PostMapping(value = "/loginByPhone")
@ApiOperation(value = "手机号登陆", response = LoginReq.class)
public Result<LoginResp> loginByPhone(@RequestBody LoginReq loginReq){
return Result.success();
@ApiOperation(value = "手机验证码登陆", response = LoginReq.class)
public Result<LoginResp> loginByPhone(@RequestBody @NotNull LoginReq loginReq){
try {
return Result.success(loginService.loginByPhone(loginReq));
}catch (Exception e){
return Result.error(e.getMessage());
}
}
// 手机号验证码登陆
@ResponseBody
@PostMapping(value = "/loginByPassword")
@ApiOperation(value = "密码登陆", response = LoginReq.class)
public Result<LoginResp> loginByPassword(@RequestBody @NotNull LoginReq loginReq){
try {
return Result.success(loginService.loginByPassword(loginReq));
}catch (Exception e){
return Result.error(e.getMessage());
}
}
public static void main(String[] args) {
System.out.println(DigestUtils.md5Hex("123456"));
}
}

View File

@ -1,4 +1,4 @@
package com.ruoyi.system.controller;
package com.ruoyi.web.controller.system;
import java.util.List;
import org.apache.shiro.authz.annotation.RequiresPermissions;

View File

@ -0,0 +1,58 @@
package com.ruoyi.web.controller.tool;
import com.ruoyi.common.core.domain.Result;
import com.ruoyi.web.request.CommonReq;
import com.ruoyi.web.service.SmsService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
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 java.util.Random;
/**
* <p>短信接口</p>
* @author clunt
*/
@Api(tags = "App**短信工具类")
@RestController
@RequestMapping(("/tool/sms"))
public class SmsController {
private static final String BASIC = "1234567890";
@Autowired
private SmsService smsService;
@ApiOperation(value = "发送短信验证码(60s有效期)")
@PostMapping(value = "/sendAuthCode")
public Result<String> sendAuthCode(@RequestBody CommonReq commonReq){
try {
if(smsService.sendSms(commonReq.getMobile(), generateAuthCode())){
return Result.success("验证码发送成功");
}else {
return Result.error("验证码发送失败");
}
}catch (Exception e){
return Result.error(e.getMessage());
}
}
/**
* @return 随机6位验证码
*/
private String generateAuthCode(){
char[] basicArray = BASIC.toCharArray();
Random random = new Random();
char[] result = new char[6];
for (int i = 0; i < result.length; i++) {
int index = random.nextInt(100) % (basicArray.length);
result[i] = basicArray[index];
}
return new String(result);
}
}

View File

@ -0,0 +1,15 @@
package com.ruoyi.web.core.config;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
@Data
@Configuration
@ConfigurationProperties(prefix = "youban.sms")
public class SmsConfig {
private String signName;
private String templateCode;
private String accessKey;
private String secret;
}

View File

@ -0,0 +1,27 @@
package com.ruoyi.web.request;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* <p>通用参数接口</p>
* @author clunt
*/
@Data
@ApiModel(value = "App*通用入参")
public class CommonReq {
@ApiModelProperty(value = "主键id")
private Long id;
@ApiModelProperty(value = "编码")
private String code;
@ApiModelProperty(value = "手机号")
private String mobile;
@ApiModelProperty(value = "名称")
private String name;
}

View File

@ -0,0 +1,12 @@
package com.ruoyi.web.service;
import com.ruoyi.web.request.LoginReq;
import com.ruoyi.web.response.LoginResp;
public interface LoginService {
LoginResp loginByPhone(LoginReq loginReq) throws Exception;
LoginResp loginByPassword(LoginReq loginReq) throws Exception;
}

View File

@ -0,0 +1,8 @@
package com.ruoyi.web.service;
public interface SmsService {
Boolean sendSms(String mobile, String code);
}

View File

@ -0,0 +1,90 @@
package com.ruoyi.web.service.impl;
import com.ruoyi.common.constant.RedisConstants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.system.domain.TbUser;
import com.ruoyi.system.domain.TbUserSingle;
import com.ruoyi.system.service.ITbUserService;
import com.ruoyi.system.service.ITbUserSingleService;
import com.ruoyi.web.request.LoginReq;
import com.ruoyi.web.response.LoginResp;
import com.ruoyi.web.service.LoginService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.Date;
@Slf4j
@Service
public class LoginServiceImpl implements LoginService {
private static final String DEFAULT_PASSWORD = "123456";
private static final String DEFAULT_CREATE_BY = "手机用户";
@Autowired
private StringRedisTemplate stringRedisTemplate;
@Autowired
private ITbUserService tbUserService;
@Autowired
private ITbUserSingleService tbUserSingleService;
@Override
public LoginResp loginByPhone(LoginReq loginReq) throws Exception{
LoginResp resp = new LoginResp();
String alreadyCode = stringRedisTemplate.opsForValue().get(RedisConstants.SMS_CODE_PREFIX+loginReq.getMobile());
if(StringUtils.isEmpty(alreadyCode)){
throw new Exception("验证码已过期!");
}
if(!alreadyCode.equals(loginReq.getAuthCode())){
throw new Exception("短信验证码错误!");
}
TbUser tbUser = tbUserService.lambdaQuery().eq(TbUser::getMobile, loginReq.getMobile()).one();
//如果用户-- 则注册新用户,只带入用户的手机号+默认密码123456
if(tbUser == null){
tbUser = new TbUser();
tbUser.setMobile(loginReq.getMobile());
tbUser.setPassword(DigestUtils.md5Hex(DEFAULT_PASSWORD));
tbUser.setCreateTime(new Date());
tbUser.setCreateBy(DEFAULT_CREATE_BY);
tbUserService.save(tbUser);
BeanUtils.copyProperties(tbUser, resp);
resp.setUserId(tbUser.getId());
}else {
BeanUtils.copyProperties(tbUser, resp);
resp.setUserId(tbUser.getId());
// 用户存在,如果已填充用户信息
TbUserSingle tbUserSingle = tbUserSingleService.lambdaQuery().eq(TbUserSingle::getUserId, tbUser.getId()).one();
BeanUtils.copyProperties(tbUserSingle, resp);
}
return resp;
}
@Override
public LoginResp loginByPassword(LoginReq loginReq) throws Exception{
LoginResp resp = new LoginResp();
TbUser tbUser = tbUserService.lambdaQuery()
.eq(TbUser::getMobile, loginReq.getMobile())
.eq(TbUser::getPassword, DigestUtils.md5Hex(loginReq.getPassword()))
.one();
//如果用户-- 则注册新用户,只带入用户的手机号+默认密码123456
if(tbUser == null){
throw new Exception("账号或密码错误!");
}else {
BeanUtils.copyProperties(tbUser, resp);
resp.setUserId(tbUser.getId());
// 用户存在,如果已填充用户信息
TbUserSingle tbUserSingle = tbUserSingleService.lambdaQuery().eq(TbUserSingle::getUserId, tbUser.getId()).one();
if(tbUserSingle != null){
BeanUtils.copyProperties(tbUserSingle, resp);
}
}
return resp;
}
}

View File

@ -0,0 +1,62 @@
package com.ruoyi.web.service.impl;
import com.aliyun.dysmsapi20170525.Client;
import com.aliyun.dysmsapi20170525.models.SendSmsRequest;
import com.aliyun.dysmsapi20170525.models.SendSmsResponse;
import com.aliyun.teaopenapi.models.Config;
import com.ruoyi.common.constant.RedisConstants;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.web.core.config.SmsConfig;
import com.ruoyi.web.service.SmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import java.util.concurrent.TimeUnit;
@Slf4j
@Service
public class SmsServiceImpl implements SmsService {
@Autowired
private SmsConfig smsConfig;
@Autowired
private StringRedisTemplate stringRedisTemplate;
private final static String ALI_SMS_URL = "dysmsapi.aliyuncs.com";
@Override
public Boolean sendSms(String mobile, String code) {
try {
String alreadyCode = stringRedisTemplate.opsForValue().get(RedisConstants.SMS_CODE_PREFIX + mobile);
if(StringUtils.isNotEmpty(alreadyCode)){
throw new Exception("已发的验证码还在有效期");
}
//配置阿里云
Config config = new Config()
// 您的AccessKey ID
.setAccessKeyId(smsConfig.getAccessKey())
// 您的AccessKey Secret
.setAccessKeySecret(smsConfig.getSecret());
// 访问的域名
config.endpoint = ALI_SMS_URL;
Client client = new Client(config);
SendSmsRequest sendSmsRequest = new SendSmsRequest()
.setPhoneNumbers(mobile)
.setSignName(smsConfig.getSignName())
.setTemplateCode(smsConfig.getTemplateCode())
.setTemplateParam("{\"code\":\""+code+"\"}");
// 复制代码运行请自行打印 API 的返回值
SendSmsResponse response = client.sendSms(sendSmsRequest);
log.info("调用阿里云成功状态:{}, 内容:{}", response.body.code, response.body.getMessage());
stringRedisTemplate.opsForValue().set(RedisConstants.SMS_CODE_PREFIX + mobile, code, 60, TimeUnit.SECONDS);
}catch (Exception e) {
log.error("调用阿里云短信异常:{}", e.getMessage());
return Boolean.FALSE;
}
return Boolean.TRUE;
}
}

View File

@ -45,6 +45,20 @@ user:
# Spring配置
spring:
# redis配置
redis:
database: 0
host: 121.62.23.77
port: 6379
password: Clunt@12345
timeout: 6000ms # 连接超时时长(毫秒)
lettuce:
pool:
max-active: 1000 # 连接池最大连接数(使用负值表示没有限制)
max-wait: -1ms # 连接池最大阻塞等待时间(使用负值表示没有限制)
max-idle: 10 # 连接池中的最大空闲连接
min-idle: 5 # 连接池中的最小空闲连接
# 模板引擎
thymeleaf:
mode: HTML
@ -71,7 +85,7 @@ spring:
devtools:
restart:
# 热部署开关
enabled: true
enabled: false
# MyBatis
mybatis:
@ -144,3 +158,11 @@ xss:
swagger:
# 是否开启swagger
enabled: true
#阿里云短信
youban:
sms:
sign-name: 深圳市有伴文化传媒
template-code: SMS_463638490
access-key: LTAI5tSVfRSePk9cfLUT5y5f
secret: qlpXG6usf0zPgQQECDAlrfYoMRHxgM

View File

@ -17,6 +17,16 @@
<dependencies>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-pool2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-all</artifactId>

View File

@ -0,0 +1,7 @@
package com.ruoyi.common.constant;
public class RedisConstants {
public final static String SMS_CODE_PREFIX = "SMS_CODE_";
}

View File

@ -62,7 +62,7 @@ public class Result<T> implements Serializable {
return success(data, "操作成功!");
}
/** @deprecated */
public static <T> Result<T> success(String msg) {
return success(null, msg);
}

View File

@ -294,9 +294,8 @@ public class ShiroConfig
filterChainDefinitionMap.put("/login", "anon,captchaValidate");
// 注册相关
filterChainDefinitionMap.put("/register", "anon,captchaValidate");
// 接口文档
filterChainDefinitionMap.put("/tool/swagger", "anon");
filterChainDefinitionMap.put("/tool/swagger/**", "anon");
// 短信文档
filterChainDefinitionMap.put("/tool/sms/**", "anon");
// app登陆接口
filterChainDefinitionMap.put("/app/login/**", "anon");
// 系统权限列表