diff --git a/pom.xml b/pom.xml index 28e97e6b..b1b93c0d 100644 --- a/pom.xml +++ b/pom.xml @@ -33,12 +33,33 @@ 2.3 5.8.22 3.0.3 + 4.5.3 + 2.0.1 + 3.10.2 + + + com.aliyun + aliyun-java-sdk-core + ${ali-sdk.version} + + + com.aliyun + dysmsapi20170525 + ${ali-sms.version} + + + + com.aliyun.oss + aliyun-sdk-oss + ${ali-oss.version} + + cn.hutool hutool-all diff --git a/ruoyi-admin/pom.xml b/ruoyi-admin/pom.xml index eaeda96f..c9e7e354 100644 --- a/ruoyi-admin/pom.xml +++ b/ruoyi-admin/pom.xml @@ -17,6 +17,21 @@ + + + com.aliyun + aliyun-java-sdk-core + + + com.aliyun + dysmsapi20170525 + + + + com.aliyun.oss + aliyun-sdk-oss + + org.springframework.boot diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/LoginController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/LoginController.java index 337ad7df..83638d76 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/LoginController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/app/LoginController.java @@ -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; + /** *

登陆相关接口

* @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 loginByPhone(@RequestBody LoginReq loginReq){ - return Result.success(); + @ApiOperation(value = "手机验证码登陆", response = LoginReq.class) + public Result 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 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")); + } } diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TbUserSingleController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TbUserSingleController.java index 8fc71365..cd60a0bb 100644 --- a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TbUserSingleController.java +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/system/TbUserSingleController.java @@ -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; diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SmsController.java b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SmsController.java new file mode 100644 index 00000000..8fbf82ae --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/controller/tool/SmsController.java @@ -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; + +/** + *

短信接口

+ * @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 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); + } + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SmsConfig.java b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SmsConfig.java new file mode 100644 index 00000000..c1f75bdd --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/core/config/SmsConfig.java @@ -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; +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/request/CommonReq.java b/ruoyi-admin/src/main/java/com/ruoyi/web/request/CommonReq.java new file mode 100644 index 00000000..aa39825a --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/request/CommonReq.java @@ -0,0 +1,27 @@ +package com.ruoyi.web.request; + +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +/** + *

通用参数接口

+ * @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; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/LoginService.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/LoginService.java new file mode 100644 index 00000000..49847f0f --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/LoginService.java @@ -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; + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/SmsService.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/SmsService.java new file mode 100644 index 00000000..d89bc95f --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/SmsService.java @@ -0,0 +1,8 @@ +package com.ruoyi.web.service; + + +public interface SmsService { + + Boolean sendSms(String mobile, String code); + +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/LoginServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/LoginServiceImpl.java new file mode 100644 index 00000000..63526c6b --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/LoginServiceImpl.java @@ -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; + } +} diff --git a/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/SmsServiceImpl.java b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/SmsServiceImpl.java new file mode 100644 index 00000000..cefafd23 --- /dev/null +++ b/ruoyi-admin/src/main/java/com/ruoyi/web/service/impl/SmsServiceImpl.java @@ -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; + } +} diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 3d7a5630..b636ac11 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -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 diff --git a/ruoyi-common/pom.xml b/ruoyi-common/pom.xml index ecc50476..d531f53f 100644 --- a/ruoyi-common/pom.xml +++ b/ruoyi-common/pom.xml @@ -17,6 +17,16 @@ + + org.apache.commons + commons-pool2 + + + + org.springframework.boot + spring-boot-starter-data-redis + + cn.hutool hutool-all diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/RedisConstants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/RedisConstants.java new file mode 100644 index 00000000..cbf5a190 --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/RedisConstants.java @@ -0,0 +1,7 @@ +package com.ruoyi.common.constant; + +public class RedisConstants { + + public final static String SMS_CODE_PREFIX = "SMS_CODE_"; + +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Result.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Result.java index d46f67ac..ecc478b3 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Result.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/Result.java @@ -62,7 +62,7 @@ public class Result implements Serializable { return success(data, "操作成功!"); } - /** @deprecated */ + public static Result success(String msg) { return success(null, msg); } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java index e25bd1e3..bc9ad063 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/ShiroConfig.java @@ -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"); // 系统权限列表