本文将详情介绍从Redis+阿里云注册短信服务到后端调用等过程。
这个功能比较实用的地方就是注册用户的时候,防止一个用户多个账户注册,因为手机号毕竟有限
短信服务
首先,打开你的阿里云
话不多说,第一步,先充钱
阿里云短信一条默认为0.045元,发短信前提是你账户余额足够,我这里充了10块,勉强够支撑200条短信。
然后我们从阿里云找到短信服务并开通
开通之后,接下来是阿里云短信服务的主界面,点击左边的国内消息,可以看到我这里已经有一条是成功的。
接着我们点击右上角添加签名
可以看见有签名、适用场景、申请说明
签名这个地方我填的魔咒,所以接收验证码后的效果就是【魔咒】
也就是签名填的是验证码前面那个公司或者个人的品牌名称
适用场景这里填验证码
申请说明尽量填一些业务方面的,通过成功率高,我也是申请了3次才过
这里个人建议:
- 签名先申请成功,再去申请模板。因为我个人就是,模板申请了三次都失败,签名第三次成功了,话说也是挺有意思,我这边是签名申请成功后,模板还等了好长时间才有结果,给我返回了个失败,然后我直接再次申请,申请说明我写了:我签名都通过了
- 然后直接这次申请就成功了,所以签名你要是成功了模板会很容易。
接下来便到了模板申请,大家也可以看见我已经有一个模板
点击右上角模板申请
这里模板类型填验证码,模板名称可以随便填,当然建议正式点,通过申请概率会大。
模板内容呢,就是:
您的验证码为:${code},该验证码 5 分钟内有效,请勿泄露于他人。
申请内容也写的正式点,不然比较难通过。
这里说一下这个短信签名和模板的这个用处
先举个例子,我网站发送注册验证码的一条例子是:先举个例子,我网站发送注册验证码的一条例子是:
【魔咒】您的验证码为:1052,该验证码 5 分钟内有效,请勿泄露于他人。
这里【魔咒】就是签名名称
后面的
您的验证码为:1052,该验证码 5 分钟内有效,请勿泄露于他人。
就是模板内容,中间的验证码则是用${code}
好了,看到这里,大家应该两个都申请成功了
记住模板管理下面那个模板Code码,后面会用到
下一步,就要去获得大家专属的AccessKey码
点击右上角头像可以找到
进去之后会弹出这个界面,点击开始使用子用户AccessKey
接着从左边人员管理中进入用户组
点击创建用户组,创建一个用户组
创建完用户组之后点击左边菜单栏的用户,并创建用户
创建用户的时候注意,编程访问勾选上
接着从左边菜单栏进入用户组,点击用户组右边的添加权限
在添加权限页面,授权应用范围选择整个云账号
被授权主体就是当前用户组
选择系统策略,然后输入sms,选中第一个管理短信服务,添加到右边点确定
完成之后,在用户组界面点击添加组成员
如下为添加用户组成员界面,将刚才新建的用户添加到当前用户组当中。
最后点击你创建的用户,到用户详情页面,下面有个用户AccessKey,点击创建AccessKey,新建一个
这里注意,新建的时候会给你一个id和密码,一定要妥善记录好。尤其是密码,关闭这个页面之后就不会在显示了。
这个id和密码一定要保护好。
下一步就要在服务器上操作一些东西了。
我的服务器是阿里云简单搞的学生机
Redis的安装与操作便不再叙述了,大家要是有问题可以私聊我
这里总结几点Redis安装时可能会遇到的问题
- Redis启动时要确保确认调用了你修改后的配置文件。
- 我的服务器是阿里云的,所以注意阿里云服务器中的端口是否开放。没有开放的话要去安全组开放
接下来就是idea,后台这边的代码,大家可以到阿里云短信服务中的快速学习复制一份demo,也可以从我下面复制
需要注意的是,阿里云有的服务器可能会报错,我这边用的北京一个节点一直报错,,后面发现换了个节点就可以了
以下为代码,先上代码,代码下面给大家讲解一下部分代码
首先是Controller
import com.alibaba.fastjson.JSON;
import com.aliyuncs.utils.StringUtils;
import com.mozhoublog.service.SendSms;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
@Controller
@CrossOrigin //跨域支持
public class SmsApiController {
@Autowired
private SendSms sendSms;
@Autowired
private RedisTemplate<String,String> redisTemplate;
@ResponseBody
@GetMapping("/SendSms/{telephone}")
public String code(@PathVariable("telephone") String telephone) throws Exception{
//从Redis中获取手机号对应验证码
String code = redisTemplate.opsForValue().get(telephone);
//如果获取的验证码不为空,说明已经存在,至于这里我为什么使用Map后面会解释。
if(!StringUtils.isEmpty(code)){
Map<String,Object> map = new HashMap<String,Object>();
map.put("message","验证码已存在,还没有过期");
//用Fastjson转为json返回
return JSON.toJSONString(map);
}
//到了这里说明手机号获得的验证码为空,生成验证码并存储到Redis中
HashMap<String,Object> param = new HashMap<>();
code = String.valueOf((int)(Math.random()*9999)+100);
param.put("code",code);
//调用发送验证码方法,将发送的手机号,短信模板,以及验证码传入
boolean isSend = sendSms.send(telephone, 短信模板Code, param);
//如果发送成功,则将手机号和验证码存入Redis,设置为2分钟后过期
if(isSend){
redisTemplate.opsForValue().set(telephone,code,2, TimeUnit.MINUTES);
Map<String,Object> map = new HashMap<String,Object>();
map.put("message","验证码发送成功!两分钟内有效");
return JSON.toJSONString(map);
}else{
Map<String,Object> map = new HashMap<String,Object>();
map.put("message","验证码发送失败!未知错误!请联系管理员!");
return JSON.toJSONString(map);
}
}
}
接下来是接口
import java.util.Map;
public interface SendSms {
public boolean send(String phoneNum, String templateCode, Map<String,Object> code) throws Exception;
}
接口实现类
import com.alibaba.fastjson.JSONObject;
import com.aliyun.dysmsapi20170525.models.*;
import com.aliyun.teaopenapi.models.*;
import org.springframework.stereotype.Service;
@Service
public class SendSmsImpl implements SendSms {
public static com.aliyun.dysmsapi20170525.Client createClient(String accessKeyId, String accessKeySecret) throws Exception {
Config config = new Config()
// 您的AccessKey ID
.setAccessKeyId(accessKeyId)
// 您的AccessKey Secret
.setAccessKeySecret(accessKeySecret);
// 访问的域名
config.endpoint = "dysmsapi.aliyuncs.com";
return new com.aliyun.dysmsapi20170525.Client(config);
}
public boolean send(String phoneNum, String templateCode, java.util.Map<String, Object> code) throws Exception{
//下面将你获得的AccessKey ID和AccessKey Secret填入
com.aliyun.dysmsapi20170525.Client client = SendSmsImpl.createClient("AccessKeyID", "AccessKeySecret");
SendSmsRequest sendSmsRequest = new SendSmsRequest()
.setPhoneNumbers(phoneNum)
.setSignName("这里填签名名称")
.setTemplateCode(templateCode)
.setTemplateParam(JSONObject.toJSONString(code));
//接收发送结果
SendSmsResponse response = client.sendSms(sendSmsRequest);
SendSmsResponseBody sendSmsResponseBody = response.getBody();
System.out.println("发送请求码:"+sendSmsResponseBody.code+"\t发送情况:"+sendSmsResponseBody.message+"发送的手机号码:"+phoneNum);
//如果发送成功返回true,否则false
if(sendSmsResponseBody.code.equals("OK")){
return true;
}else{
return false;
}
}
}
这里说一下FastJson的问题,如果直接return “验证码已存在,还没有过期”;
你就会发现网页上返回信息中成了"验证码已存在,还没有过期",多出了双引号。
但是用HashMap转json不会出现这个问题
最后来相对应的pom给大家参考
<dependencies>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>dysmsapi20170525</artifactId>
<version>2.0.1</version>
</dependency>
<dependency>
<groupId>com.aliyun</groupId>
<artifactId>aliyun-java-sdk-core</artifactId>
<version>4.5.3</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.62</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
</dependencies>
前端我使用的ajax进行请求发送,下面是我的部分源码
<body>
<div>
<input type="text" name="telephone" class="phone_number" placeholder="输入手机号码" autocomplete="off" id="telephone"/>
</div>
<div>
<button id='getcode' name="getcode" class="send-tis">免费获取验证码</button>
</div>
<script src="js/jquery-3.4.1.js"></script>
<script type="text/javascript">
var waitTime = 120;
document.getElementById("getcode").onclick = function() {
send();
time(this);
}
function send(){
$.ajax({
url:"SendSms/"+$("#telephone").val(),
type:"get",
success:function(msg){
alert(JSON.parse(msg).message);
}
});
}
function time(ele) {
if (waitTime == 0) {
ele.disabled=false;
ele.innerHTML = "免费获取验证码";
waitTime = 120;// 恢复计时
} else {
ele.disabled=true;
ele.innerHTML = waitTime + "秒后可以重新发送";
waitTime--;
setTimeout(function() {
time(ele)// 关键处-定时循环调用
}, 1000)
}
}
</script>
</body>
在Idea application.yml中记得配置Redis
spring:
redis:
host: 服务器地址
port: 端口
password: Redis密码