Commit 91353747 authored by liming's avatar liming

feat(初始化项目): 增加缓存和登录用户注入

parent fd9c4a7a
......@@ -79,5 +79,13 @@
<artifactId>constants</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
......@@ -29,12 +29,12 @@ public class GlobalControllerExceptionHandler {
public String profile;
@ExceptionHandler(value = Exception.class)
public ResponseEntity<Result> businessExceptionHandler(HttpServletRequest req, Exception e, Model model) {
public ResponseEntity<Result> businessExceptionHandler(HttpServletRequest req, Exception e, Model model) {
String operateUser = "no-user";
//日志打印异常
String errorCode = UUIDUtil.createUUID().substring(0, 8);
logger.error(operateUser + "->request:" + req.getRequestURI() + "-异常代码:" + errorCode + "-" + e.getMessage());
logger.error(operateUser + "->request:" + req.getRequestURI() + "-异常代码:" + errorCode, e);
Result baseDTO = new Result();
if (e instanceof BusinessException) {
baseDTO.setRespCode(RespCodeEnum.BUSINESS_ERROR.getCode());
......
package com.antai.sport.http.server.common.service;
import com.antai.sport.http.server.common.util.SmsUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Map;
/**
* @Author liming
* @Date 2021/8/23 10:51
* @Email lmmax@126.com
* @Description:
*/
@Service
public class CommonSmsService {
Logger logger = LoggerFactory.getLogger(CommonSmsService.class);
@Value("${aliyun.sms.sign}")
private String sign;
@Value("${aliyun.sms.template-code.login}")
private String loginTemplateCode;
@Resource
private SmsUtil smsUtil;
public void sendLoginSmsCaptcha(String phone, String code) {
try {
String errorMsg = smsUtil.sendSms(sign, loginTemplateCode, Map.of("code", code), phone);
if (errorMsg != null) {
logger.error(errorMsg);
}
} catch (Exception ex) {
logger.error("短信发送失败", ex);
}
}
}
package com.antai.sport.http.server.common.util;
/**
* @Author liming
* @Date 2021/8/23 11:10
* @Email lmmax@126.com
* @Description:
*/
public class RandomUtil {
/**
* 获取6位纯数字
*/
public static Integer generateNum() {
return (int) ((Math.random() * 9 + 1) * 100000);
}
}
package com.antai.sport.http.server.common.util;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest;
import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Map;
/**
* @author 厉明
* @date 2019/12/17 10:14
* @email lmmax@126.com
* @description 短信发送工具
*/
@Service
@Slf4j
public class SmsUtil {
@Value("${aliyun.access-key-id}")
private String accessKeyId;
@Value("${aliyun.access-key-secret}")
private String accessKeySecret;
@Value("${aliyun.sms.region-id}")
private String regionId;
@Value("${aliyun.sms.time-out}")
private String timeOut;
static final String PRODUCT = "Dysmsapi";
static final String DOMAIN = "dysmsapi.aliyuncs.com";
static final String SUCCEED_STATUS = "OK";
@Resource
private ObjectMapper objectMapper;
/**
* 发送短信
*
* @param sign 签名
* @param templateCode 短信模板
* @param templateParam 模板参数
* @param phoneNums 电话号码
* @return 短信发送结果
* @throws ClientException 客户端异常
* @throws JsonProcessingException json转换异常
*/
public String sendSms(String sign, String templateCode, Map<String, Object> templateParam, String... phoneNums) throws ClientException, JsonProcessingException {
if (phoneNums.length > 1000) {
return "最大发送数量不能超过1000";
}
//设置超时时间-可自行调整
System.setProperty("sun.net.client.defaultConnectTimeout", timeOut);
System.setProperty("sun.net.client.defaultReadTimeout", timeOut);
//初始化ascClient需要的几个参数
//初始化ascClient,暂时不支持多region(请勿修改)
IClientProfile profile = DefaultProfile.getProfile(regionId, accessKeyId, accessKeySecret);
DefaultProfile.addEndpoint(regionId, PRODUCT, DOMAIN);
IAcsClient acsClient = new DefaultAcsClient(profile);
//组装请求对象
SendSmsRequest request = new SendSmsRequest();
//必填:待发送手机号。支持以逗号分隔的形式进行批量调用,批量上限为1000个手机号码,批量调用相对于单条调用及时性稍有延迟,验证码类型的短信推荐使用单条调用的方式;发送国际/港澳台消息时,接收号码格式为00+国际区号+号码,如“0085200000000”
String phoneNumbsers = StringUtils.join(phoneNums, ",");
request.setPhoneNumbers(phoneNumbsers);
//必填:短信签名-可在短信控制台中找到
request.setSignName(sign);
//必填:短信模板-可在短信控制台中找到
request.setTemplateCode(templateCode);
//可选:模板中的变量替换JSON串,如模板内容为"亲爱的${name},您的验证码为${code}"时,此处的值为
//友情提示:如果JSON中需要带换行符,请参照标准的JSON协议对换行符的要求,比如短信内容中包含\r\n的情况在JSON中需要表示成\\r\\n,否则会导致JSON在服务端解析失败
//阿里云单个变量长度限制在20字符内
request.setTemplateParam(objectMapper.writeValueAsString(templateParam));
//请求失败这里会抛ClientException异常
SendSmsResponse sendSmsResponse = acsClient.getAcsResponse(request);
if (sendSmsResponse.getCode() != null && SUCCEED_STATUS.equals(sendSmsResponse.getCode())) {
log.info("阿里云短信发送成功:" + StringUtils.join(phoneNums));
return null;
} else {
log.error("阿里云短信发送失败状态码:" + StringUtils.join(phoneNums) + "-" + sendSmsResponse.getCode());
return sendSmsResponse.getCode();
}
}
}
......@@ -10,5 +10,5 @@ public class LoginMode {
//密码登录
public final static Integer PASSWORD = 1;
//短信验证码登录
public final static Integer SMS_CAPTCHA = 1;
public final static Integer SMS_CAPTCHA = 2;
}
package com.antai.sport.http.server.game.api.business.sport.user;
import com.antai.sport.http.server.common.annotation.LoginSportUser;
import com.antai.sport.http.server.common.base.Result;
import com.antai.sport.http.server.game.api.business.sport.user.dto.ReqLogin;
import com.antai.sport.http.server.repository.sport.entity.SportUser;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
......@@ -35,9 +30,10 @@ public class SportUserController {
return success(sportUserService.login(param));
}
@GetMapping("/test")
public ResponseEntity<Result> test(@LoginSportUser SportUser sportUser) {
System.out.println(1);
return success("test");
@ApiOperation(value = "获取登录短信验证码")
@GetMapping("/login/sms/captcha/{phone}")
public ResponseEntity<Result> sendLoginSmsCaptcha(@PathVariable String phone) {
sportUserService.sendLoginSmsCaptcha(phone);
return success(true);
}
}
......@@ -5,6 +5,8 @@ import com.antai.sport.http.server.common.base.Result;
import com.antai.sport.http.server.common.exception.BusinessException;
import com.antai.sport.http.server.common.jwt.TokenService;
import com.antai.sport.http.server.common.jwt.TokenVO;
import com.antai.sport.http.server.common.service.CommonSmsService;
import com.antai.sport.http.server.common.util.RandomUtil;
import com.antai.sport.http.server.constants.DeleteStatus;
import com.antai.sport.http.server.constants.LoginMode;
import com.antai.sport.http.server.game.api.business.sport.user.dto.ReqLogin;
......@@ -12,11 +14,14 @@ import com.antai.sport.http.server.repository.sport.entity.SportUser;
import com.antai.sport.http.server.repository.sport.mapper.SportUserMapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.DigestUtils;
import javax.annotation.Resource;
import java.util.List;
import java.util.concurrent.TimeUnit;
/**
* @Author liming
......@@ -26,11 +31,19 @@ import java.util.List;
*/
@Service
public class SportUserService {
@Value("${spring.cache.redis.keys.login-sms-captcha}")
private String loginSmsCaptchaRedisKey;
@Value("${spring.cache.redis.expire.login-sms-captcha}")
private long loginSmsCaptchaExpire;
@Resource
private SportUserMapper sportUserMapper;
@Resource
private TokenService tokenService;
@Resource
private CommonSmsService commonSmsService;
@Resource
private RedisTemplate<String, Object> redisTemplate;
public Result login(ReqLogin param) {
if (param.getMode() == null || (!param.getMode().equals(LoginMode.PASSWORD) && !param.getMode().equals(LoginMode.SMS_CAPTCHA))) {
......@@ -56,21 +69,40 @@ public class SportUserService {
throw new BusinessException("请输入密码");
}
String hashPwd = DigestUtils.md5DigestAsHex(param.getPassword().getBytes());
if (hashPwd.equals(sportUser.getPassword())) {
result.setRespMsg("登录成功");
TokenVO tokenVO = tokenService.initToken(param.getUsername());
result.setLongToken(tokenVO.getLongToken());
result.setShortToken(tokenVO.getShortToken());
result.setData(true);
} else {
if (!hashPwd.equals(sportUser.getPassword())) {
throw new BusinessException("用户名或密码错误");
}
} else {
if (StringUtils.isBlank(param.getSmsCaptcha())) {
throw new BusinessException("请输入验证码");
}
String redisKey = loginSmsCaptchaRedisKey + param.getUsername();
Object redisValue = redisTemplate.opsForValue().get(redisKey);
if (redisValue == null) {
throw new BusinessException("请先获取验证码");
}
String loginSmsCaptcha = redisValue.toString();
if (!loginSmsCaptcha.equals(param.getSmsCaptcha())) {
throw new BusinessException("短信验证码错误");
}
redisTemplate.delete(redisKey);
}
result.setRespMsg("登录成功");
TokenVO tokenVO = tokenService.initToken(param.getUsername());
result.setLongToken(tokenVO.getLongToken());
result.setShortToken(tokenVO.getShortToken());
result.setData(true);
return result;
}
/**
* 发送验证码逻辑
* @param phone 电话号码
*/
public void sendLoginSmsCaptcha(String phone) {
String code = String.valueOf(RandomUtil.generateNum());
commonSmsService.sendLoginSmsCaptcha(phone, code);
redisTemplate.opsForValue().set(loginSmsCaptchaRedisKey + phone, code, loginSmsCaptchaExpire, TimeUnit.SECONDS);
}
}
......@@ -9,6 +9,11 @@ spring:
redis:
use-key-prefix: true
time-to-live: 1d
expire:
login-sms-captcha: 600
keys:
login-sms-captcha: login:sms-captcha
redis:
timeout: 10s
jedis:
......@@ -39,6 +44,7 @@ project:
- /favicon.ico
- /error
- /login
- /login/sms/**
swagger:
enable: false
......@@ -51,4 +57,14 @@ swagger:
description: 接口文档
service-website: https://www.antaikeji.top/
ignored-parameter-list:
- com.antai.sport.http.server.repository.base.entity.BaseArea
\ No newline at end of file
- com.antai.sport.http.server.repository.sport.entity.SportUser
aliyun:
access-key-id: LTAI4FivP3A9hfXzF5Z2KKNM
access-key-secret: W1erPY4SLOoPK0YwwptLZCSfZ61K4c
sms:
sign: 安泰实业
region-id: cn-qingdao
time-out: 1000
template-code:
login: SMS_136440120 #登录确认验证码
......@@ -35,6 +35,8 @@
<jaxb.version>2.3.0</jaxb.version>
<activation.version>1.1.1</activation.version>
<commons.lang3.version>3.7</commons.lang3.version>
<aliyun-sdk.version>4.4.6</aliyun-sdk.version>
<aliyun-dysmsapi.version>1.1.0</aliyun-dysmsapi.version>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
......@@ -101,6 +103,16 @@
<artifactId>activation</artifactId>
<version>${activation.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>${aliyun-sdk.version}</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-dysmsapi</artifactId>
<version>${aliyun-dysmsapi.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment