@[TOC]
1、前言
接上文 SpringBoot 整合 Spring Security 实现自定义页面以及验证码登录
环境版本说明
MongoDB:5.0.6
SpringBoot:2.5.3
JDK:1.8
2、腾讯云短信 api
介绍
本 demo 使用免费赠送的腾讯云短信
https://curl.qcloud.com/a18eCzrO
短信试用有 100 个
https://console.cloud.tencent.com/smsv2
在这里通过模板还会赠送 100 个
如果不够可以购买
如果觉得短信验证麻烦可换成邮箱验证码
3、主要代码
完整代码链接放文末
pom.xml
这里建议根据 api 文档更换 jar 版本
https://console.cloud.tencent.com/api/explorer?Product=sms
<!--邮件依赖-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mail</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.tencentcloudapi/tencentcloud-sdk-java-sms -->
<dependency>
<groupId>com.tencentcloudapi</groupId>
<artifactId>tencentcloud-sdk-java-sms</artifactId>
<version>3.1.468</version>
</dependency>
application.yml
sendSms:
SecretId: 你的账号API 密钥id
SecretKey: 你的账号API 密钥
SmsSdkAppId: 你的短信应用id
TemplateId: 你的短信模板id
获取 SecretId 和 SecretKey
这里的账号 api 密钥 https://console.cloud.tencent.com/cam
快速创建账户,或者直接使用主账号
如图 访问方式使用: 编程访问;用户权限:使用预设的短信全读全写,就够了
这样就得到了 SecretId 和 SecretKey
获取 SmsSdkAppId 和 TemplateId
去短信--> 应用管理--> 应用列表获取你的应用 id SmsSdkAppId 没有就新建一个
https://console.cloud.tencent.com/smsv2/app-manage
去短信--> 国内短信--> 正文模板管理 获取你审核通过的模板 id TemplateId 没有就新建一个等待审核通过
TxSmsServiceImpl.java 发送短信
package com.king.security.service;
import com.king.security.util.MyException;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.sms.v20210111.SmsClient;
import com.tencentcloudapi.sms.v20210111.models.SendSmsRequest;
import com.tencentcloudapi.sms.v20210111.models.SendSmsResponse;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
/**
* @program: springboot
* @description: 发送短信
* @author: King
* @create: 2022-03-17 15:12
*/
@Service
public class TxSmsServiceImpl {
@Value(value = "${sendSms.SecretId}")
private String secretId; //
@Value(value = "${sendSms.SecretKey}")
private String secretKey;
@Value(value = "${sendSms.SmsSdkAppId}")
private String SmsSdkAppId;
@Value(value = "${sendSms.TemplateId}")
private String TemplateId;
private final Logger logger = LoggerFactory.getLogger(this.getClass());
//更改短信模板id
public void setTemplateId(String templateId) {
TemplateId = templateId;
}
/**
* 发送短信
* @param phoneNumber 电话号码
* @param smsCode 验证码
* @return
*/
public String sendSmsCode(String phoneNumber, String smsCode) throws MyException {
try {
Credential cred = new Credential(secretId, secretKey);
HttpProfile httpProfile = new HttpProfile();
httpProfile.setEndpoint("sms.tencentcloudapi.com");
// 实例化一个client选项,可选的,没有特殊需求可以跳过
ClientProfile clientProfile = new ClientProfile();
clientProfile.setHttpProfile(httpProfile);
// 实例化要请求产品的client对象,clientProfile是可选的
SmsClient client = new SmsClient(cred, "ap-guangzhou", clientProfile);
// 实例化一个请求对象,每个接口都会对应一个request对象
SendSmsRequest req = new SendSmsRequest();
req.setPhoneNumberSet(new String[]{phoneNumber});
req.setSmsSdkAppId(SmsSdkAppId);
req.setTemplateId(TemplateId);
//SignName – 短信签名内容,使用 UTF-8 编码,必须填写已审核通过的签名,例如:腾讯云,
// 签名信息可前往 [国内短信](https://console.cloud.tencent.com/smsv2/csms-sign)
// 的签名管理查看。 发送国内短信该参数必填。
req.setSignName("花草信息个人网");
//对应短信模板的内容 测试只支持数字字符串
//您正在申请手机注册,验证码为:{1},{2}分钟内有效!
String[] templateParamSet1 = {smsCode, "30"};
req.setTemplateParamSet(templateParamSet1);
// 返回的resp是一个SendSmsResponse的实例,与请求对象对应
SendSmsResponse resp = client.SendSms(req);
// 输出json格式的字符串回包
logger.info(SendSmsResponse.toJsonString(resp));
return resp.getSendStatusSet()[0].getMessage();
} catch (TencentCloudSDKException e) {
logger.error(e.toString());
throw new MyException(e.getMessage());
}
}
}
CodeController.java 发送验证码
package com.king.security.controller;
import com.king.security.service.TxSmsServiceImpl;
import com.king.security.util.MyException;
import com.king.security.util.StringUtils;
import com.king.security.vo.ResultObj;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
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.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.security.PermitAll;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
/**
* @program: springboot
* @description:
* @author: King
* @create: 2022-03-18 13:27
*/
@RestController
@PermitAll
@RequestMapping("/api/code")
@Api(value = "验证码接口", tags = "验证码接口")
public class CodeController {
@Autowired
private TxSmsServiceImpl txSmsService;
@ApiOperation(value = "发送注册验证码", httpMethod = "POST")
@ApiImplicitParam(name = "phone", value = "电话号码", dataType = "string", paramType = "query", example = "13788888888", required = true)
@PostMapping("/sendSms.do")
public ResultObj sendCodeRegister(String phone, HttpServletRequest request) {
try {
StringUtils.isPhone(phone);
HttpSession session = request.getSession();
Date lastDate = (Date) session.getAttribute("code_date");
if (lastDate != null && (new Date().getTime() - lastDate.getTime()) < (1000 * 120)) {
return ResultObj.error("别点了,等" + (120 - ((new Date().getTime() - lastDate.getTime()) / 1000)) + "秒后再点");
} else {
String code = StringUtils.getInt(6);
session.setAttribute("code", code);//存验证码到session
session.setAttribute("code_date", new Date());//存当前时间到session
return ResultObj.ok(txSmsService.sendSmsCode(phone, code));
}
} catch (MyException e) {
return ResultObj.error(e);
}
}
}
4、效果展示
欢迎来到这里!
我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。
注册 关于