首先在LoginController
中注入LoginService
,如下
@RestController
@Tag(name = "登录管理")
@RequestMapping("/app/")
public class LoginController {
@Autowired
private LoginService service;
}
该接口需向登录手机号码发送短信验证码,各大云服务厂商都提供短信服务,本项目使用阿里云完成短信验证码功能,下面介绍具体配置。
配置短信服务
开通短信服务
在阿里云官网,注册阿里云账号,并按照指引,完成实名认证(不认证,无法购买服务)
找到短信服务,选择免费开通
进入短信服务控制台,选择快速学习和测试
找到发送测试下的API发送测试,绑定测试用的手机号(只有绑定的手机号码才能收到测试短信),然后配置短信签名和短信模版,这里选择[专用]测试签名/模版。
创建AccessKey
云账号 AccessKey 是访问阿里云 API 的密钥,没有AccessKey无法调用短信服务。点击页面右上角的头像,选择AccessKey管理,然后创建AccessKey。
配置所需依赖
如需调用阿里云的短信服务,需使用其提供的SDK,具体可参考官方文档。
在common模块的pom.xml文件中增加如下内容
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
</dependency>
配置发送短信客户端
application.yml
中增加如下内容aliyun:
sms:
access-key-id: <access-key-id>
access-key-secret: <access-key-secret>
endpoint: dysmsapi.aliyuncs.com
注意:
上述access-key-id
、access-key-secret
需根据实际情况进行修改。
com.atguigu.lease.common.sms.AliyunSMSProperties
类,内容如下@Data
@ConfigurationProperties(prefix = "aliyun.sms")
public class AliyunSMSProperties {
private String accessKeyId;
private String accessKeySecret;
private String endpoint;
}
com.atguigu.lease.common.sms.AliyunSmsConfiguration
类,内容如下@Configuration
@EnableConfigurationProperties(AliyunSMSProperties.class)
@ConditionalOnProperty(name = "aliyun.sms.endpoint")
public class AliyunSMSConfiguration {
@Autowired
private AliyunSMSProperties properties;
@Bean
public Client smsClient() {
Config config = new Config();
config.setAccessKeyId(properties.getAccessKeyId());
config.setAccessKeySecret(properties.getAccessKeySecret());
config.setEndpoint(properties.getEndpoint());
try {
return new Client(config);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
配置Redis连接参数
spring:
data:
redis:
host: 192.168.10.101
port: 6379
database: 0
编写Controller层逻辑
在LoginController
中增加如下内容
@GetMapping("login/getCode")
@Operation(summary = "获取短信验证码")
public Result getCode(@RequestParam String phone) {
service.getSMSCode(phone);
return Result.ok();
}
编写Service层逻辑
编写发送短信逻辑
在SmsService
中增加如下内容
void sendCode(String phone, String verifyCode);
在SmsServiceImpl
中增加如下内容
@Override
public void sendCode(String phone, String code) {
SendSmsRequest smsRequest = new SendSmsRequest();
smsRequest.setPhoneNumbers(phone);
smsRequest.setSignName("阿里云短信测试");
smsRequest.setTemplateCode("SMS_154950909");
smsRequest.setTemplateParam("{\"code\":\"" + code + "\"}");
try {
client.sendSms(smsRequest);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
编写生成随机验证码逻辑
在common模块中创建com.atguigu.lease.common.utils.VerifyCodeUtil
类,内容如下
public class VerifyCodeUtil {
public static String getVerifyCode(int length) {
StringBuilder builder = new StringBuilder();
Random random = new Random();
for (int i = 0; i < length; i++) {
builder.append(random.nextInt(10));
}
return builder.toString();
}
}
编写获取短信验证码逻辑
在LoginServcie
中增加如下内容
void getSMSCode(String phone);
在LoginServiceImpl
中增加如下内容
@Override
public void getSMSCode(String phone) {
//1. 检查手机号码是否为空
if (!StringUtils.hasText(phone)) {
throw new LeaseException(ResultCodeEnum.APP_LOGIN_PHONE_EMPTY);
}
//2. 检查Redis中是否已经存在该手机号码的key
String key = RedisConstant.APP_LOGIN_PREFIX + phone;
boolean hasKey = redisTemplate.hasKey(key);
if (hasKey) {
//若存在,则检查其存在的时间
Long expire = redisTemplate.getExpire(key, TimeUnit.SECONDS);
if (RedisConstant.APP_LOGIN_CODE_TTL_SEC - expire < RedisConstant.APP_LOGIN_CODE_RESEND_TIME_SEC) {
//若存在时间不足一分钟,响应发送过于频繁
throw new LeaseException(ResultCodeEnum.APP_SEND_SMS_TOO_OFTEN);
}
}
//3.发送短信,并将验证码存入Redis
String verifyCode = VerifyCodeUtil.getVerifyCode(6);
smsService.sendCode(phone, verifyCode);
redisTemplate.opsForValue().set(key, verifyCode, RedisConstant.APP_LOGIN_CODE_TTL_SEC, TimeUnit.SECONDS);
}
注意:
需要注意防止频繁发送短信。
推荐阅读: