简单几步,用云开发搞定短信验证码登录
短信验证码登录支持在客户端使用短信验证码进行登录,封装了短信验证码的生成、发送、校验和定时清理逻辑,帮助开发者进行鉴权。登录成功后,用户身份将转化为正式用户。
本次实战我们将使用web云开发实现短信验证码登录并新增数据。
资源准备
- 云开发环境
- 腾讯云短信服务
- 短信验证码登录扩展能力
- 静态网站托管
一、云开发环境开通
如果已有云环境,可直接跳过这一步
打开云开发控制台新建云环境:
创建云开发环境
打开云开发 CloudBase 控制台,打开左侧菜单里的数据库,点击添加集合,新增一个test
集合用于新增数据测试。
添加集合
二、腾讯云短信服务
- 开通短信服务
登录腾讯云短信控制台,这里的账号不限于小程序的账号,其他账号也可以;也不限于是个人账号还是企业账号,不过账号需要进行实名认证,个人认证用户只能发送短信验证码、短信通知等,不能用于营销短信;企业认证用户可以发送短信验证码、短信通知、营销短信等。如果账号已经认证,直接申请短信服务就可以开通了。
- 创建签名和正文模板
国内短信由签名+正文组成,签名符号为【】,发送短信内容时必须带签名。所以要发送短信,需要申请短信签名和正文模板,两者都通过审核后,就可以开始发送短信了。
创建签名
打开左侧菜单里的国内短信-签名管理,点击创建签名,创建完签名后,这个签名内容
之后会用到。
- 签名用途:选择【自用(签名为本账号实名认证的公司、网站、产品名等)】。
- 签名类型:选择【公众号】。
- 签名内容:输入公司名或小程序名或公众号名或产品名称
- 证明类型:选择公众号设置页面截图,然后上传小程序设置页面截图,可以参考案例;
创建签名
创建正文模板
打开左侧菜单里的国内短信-正文模板管理,点击创建正文模板,创建完模板后,会有一个模板ID
,这个之后会用到,也要记住你模板的变量位置。
- 模板名称,建议带有明确目的的名称,比如“注册通知”、“购买成功反馈”等;
- 短信类型:选择【普通短信】
- 短信内容:比如“您正在申请手机注册,验证码为:{1},{2}分钟内有效!”,这里的
{1}
和{2}
是你要在代码里传入的变量,变量的编码必须是从{1}开始,传入变量时也要按照顺序传入
创建正文模板
三、短信验证码登录扩展能力
打开云开发 CloudBase 控制台,打开左侧菜单里的扩展能力,点击短信验证码登录模块进行安装。
安装短信登录扩展
该扩展会创建以下云资源:
云函数:
- tcb-sms-auth 生成校验码并发送到指定手机号,以实现短信验证码登录
云数据库:
- tcb-sms-auth 存储验证码相关信息。
根据提示完成配置和安装。
四、开通静态网站托管
云开发为开发者提供静态网页托管的能力,静态资源(HTML、CSS、JavaScript、字体等)的分发由对象存储 COS 和拥有多个边缘网点的 CDN 提供支持。您可在腾讯云控制台进行静态网站的部署,提供给您的用户访问。
打开云开发 CloudBase 控制台,打开左侧菜单里的静态网站托管,点击开启使用,然后等待几分钟便可初始化完成。
静态网站托管
在 web 网站使用该扩展,请先在 云开发控制台 将网站域名添加为当前环境的安全域名。
打开云开发 CloudBase 控制台,复制静态网站托管-基础配置里的默认域名,然后打开左侧菜单里的环境-安全配置,将默认域名添加为WEB安全域名。
添加web安全域名
一、使用方法
- 安装扩展 SDK 到项目
- 方法一:通过包管理器引入
npm install --save @cloudbase/extension-sms
- 方法二:通过CDN引入
<script src="//unpkg.com/@cloudbase/extension-sms/built/index.umd.js"></script>
- 调用扩展 SDK
调用参数
名称 |
类型 |
是否必须 |
说明 |
---|---|---|---|
action |
String |
是 |
操作类型,支持 Send 和 Login |
phone |
String |
是 |
电话号码 |
app |
Tcb |
是 |
tcb实例 |
smsCode |
String |
否 |
短信验证码,action 为 Login 时需要传入 |
customDomain |
String |
否 |
HTTP触发的自定义域名 |
返回内容
目前两种 action 都没有返回值。(本例采用 auth.hasLoginState()
来判断登录 )
二、编写代码
写了一个简单的demo来实现登录并新增数据功能,代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="Pragma" content="no-cache">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no" />
<meta name="format-detection" content="telephone=yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<title>腾讯云云开发短信验证码登录</title>
<!-- Bootstrap core CSS-->
<!-- 最新版本的 Bootstrap 核心 CSS 文件 -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/3.3.7/css/bootstrap.min.css">
<style type="text/css">
body {
margin: 0;
padding: 0;
}
.modal_content {
padding: 30px;
display: flex;
justify-content: center;
flex-direction: column;
}
.modal_content>div {
margin-bottom: 20px;
}
.modal_content>h5:first-child {
margin: 30px 0px;
}
#dialog label {
color: #666;
}
#phone1 {
display: block;
width: 100%;
height: 70px;
background: none;
padding-top: 30px;
border: 0;
outline: none;
text-align: center;
margin-top: -30px;
font-size: 16px;
border-bottom: 1px solid rgba(0, 0, 0, .2);
border-radius: 0;
}
.code1 {
display: flex;
flex-direction: row;
justify-content: space-between;
width: 100%;
height: 70px;
background: none;
padding-top: 30px;
margin-top: -30px;
font-size: 16px;
border-bottom: 1px solid rgba(0, 0, 0, .2);
border-radius: 0;
}
#code1 {
width: calc(100% - 90px);
height: 55px;
background: none;
padding-top: 20px;
border: 0;
outline: none;
text-align: center;
margin-top: -20px;
font-size: 16px;
}
#btnSendCode1 {
width: 90px;
height: 30px;
padding: 0 5px;
margin: 0;
font-size: 14px;
text-align: center;
background: transparent;
border-radius: 30px;
color: #a07941;
border-color: #a07941;
}
::-webkit-input-placeholder {
/* WebKit browsers */
font-size: 14px;
color: rgba(0, 0, 0, .4);
}
:-moz-placeholder {
/* Mozilla Firefox 4 to 18 */
font-size: 14px;
color: rgba(0, 0, 0, .4);
}
::-moz-placeholder {
/* Mozilla Firefox 19+ */
font-size: 14px;
color: rgba(0, 0, 0, .4);
}
:-ms-input-placeholder {
/* Internet Explorer 10+ */
font-size: 14px;
color: rgba(0, 0, 0, .4);
}
.next {
text-align: center;
margin: 20px 0;
}
.next button {
width: 100%;
height: 45px;
padding: 0;
margin: 0;
background: #007BFF;
color: #fff;
border: 0;
outline: none;
border-radius: 3px;
}
.content2{
display:none;
}
</style>
</head>
<body>
<div class="modal_content content1">
<h5>用户登录</h5>
<div>
<label for="phone1">手机号:</label><br />
<input id="phone1" type="text" autocomplete="off" placeholder="请输入手机号" />
</div>
<div>
<label for="code1">验证码:</label>
<div class="code1">
<input id="code1" type="text" autocomplete="off" placeholder="短信验证码" />
<input id="btnSendCode1" type="button" class="btn btn-default" value="获取验证码" onClick="sendMessage1()" />
</div>
</div>
<div class="next">
<button onClick="binding()">确定</button>
</div>
</div>
<div class="modal_content content2">
<h5>新增数据</h5>
<div>
<label for="text1">文本:</label><br />
<input id="text1" type="text" placeholder="请输入新增的数据" />
</div>
<div class="next">
<button onClick="add()">确定</button>
</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.9.1/jquery.js"></script>
<script src="//imgcache.qq.com/qcloud/tcbjs/1.7.1/tcb.js"></script>
<script src="//unpkg.com/@cloudbase/extension-sms/built/index.umd.js"></script>
<script>
const app = tcb.init({
env: 'env-jftmiosg'
});
const auth = app.auth();
var db = app.database();
tcb.registerExtension(window.extSms);
islogin();
var phoneReg = /(^1[3|4|5|7|8]d{9}$)|(^09d{8}$)/;//手机号正则
var count = 60; //间隔函数,1秒执行
var InterValObj1; //timer变量,控制时间
var curCount1;//当前剩余秒数
function islogin(){
if (auth.hasLoginState()) {
// 此时已经登录
$(".content1").hide();
$(".content2").show();
return true;
}
return false;
}
/*第一*/
async function sendMessage1() {
curCount1 = count;
var phone = $.trim($('#phone1').val());
if (!phoneReg.test(phone)) {
alert(" 请输入有效的手机号码");
return false;
}
//设置button效果,开始计时
$("#btnSendCode1").attr("disabled", "true");
$("#btnSendCode1").val(+ curCount1 + "秒再获取");
InterValObj1 = window.setInterval(SetRemainTime1, 1000); //启动计时器,1秒执行一次
//向后台发送处理数据
try {
await tcb.invokeExtension(extSms.name, {
action: 'Send',
app,
phone
});
} catch (err) {
console.log(JSON.stringify(err, null, 4));
}
}
function SetRemainTime1() {
if (curCount1 == 0) {
window.clearInterval(InterValObj1);//停止计时器
$("#btnSendCode1").removeAttr("disabled");//启用按钮
$("#btnSendCode1").val("重新发送");
}
else {
curCount1--;
$("#btnSendCode1").val(+ curCount1 + "秒再获取");
}
}
/*提交*/
async function binding() {
var phone = $.trim($('#phone1').val());
var smsCode = $.trim($('#code1').val());
try {
await tcb.invokeExtension(extSms.name, {
action: 'Login',
app,
phone,
smsCode,
});
} catch (err) {
console.log(JSON.stringify(err, null, 4));
} finally {
//无论try catch结果如何还是继续执行
if(islogin()){
alert("登录成功,目前是正式用户");
}else{
alert("登录失败,请检查验证码");
}
}
}
async function add() {
try {
var text = $.trim($('#text1').val());
await db.collection("test").add({
text:text
}).then(res => {
alert("数据新增成功");
console.log(res);
})
.catch(e => {
alert("数据新增失败");
console.log(e);
});
} catch (err) {
console.log(JSON.stringify(err, null, 4));
}
}
</script>
</body>
</html>
三、上传部署
完成demo编写后,将代码上传至静态网站托管,完成部署。
- 控制台上传
打开云开发 CloudBase 控制台,打开左侧菜单里的静态网站托管,将刚刚编写的文件sms.html
上传。
上传文件
- CLI 工具上传
CloudBase CLI 是一个开源的命令行界面交互工具,用于帮助用户快速、方便的部署项目,管理云开发资源。具体安装步骤和使用方法可以访问云开发 CLI 工具文档进行查看。
- 发送短信
发送短信
- 登录验证
登录验证
- 新增数据
新增数据
总结
通过上述步骤,利用云开发提供的短信验证码登录扩展能力,配合云开发的SDK在web端很方便的实现了自定义登录并新增数据,大家快去试试吧!
- Md5加密秘钥加密哈希加密
- JavaSE(十二)之IO流的字节流(一)
- 基于ASP.MVC票据FormsAuthenticationTicket身份认证
- AI需要大数据,而大数据也需要AI
- Java进阶09 事件响应
- JavaSE(十一)之异常处理详解
- 微信开发扫一扫功能并且屏蔽分享菜单
- HTML语义化:HTML5新标签——template
- 纸上谈兵: 左倾堆 (leftist heap)
- 统计Go, Go, Go
- 前端构建:Source Maps详解
- 解决YUM下Loaded plugins: fastestmirror Determining fastest mirrors 的问题
- 被解放的姜戈01 初试天涯
- 被解放的姜戈02 庄园疑云
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 面试Java基础问题汇总 part2
- org.springframework.util.xml.SimpleSaxErrorHandler warning org.xml.sax.SAXParseException; systemId:
- 贷款违约预测-Task1 赛题理解
- Android功耗优化(7)---如何分析wakelock(wakeup source)持锁问题
- 一道有意思的腾讯算法面试题
- 关于 JavaScript 错误处理的最完整指南(上半部)
- 排障集锦:九九八十一难之第十六难!-------------enoent ENOENT: no such file or directory, open ‘/root/package.json‘
- 大点干!早点散----------深入剖析GFS分布式文件系统
- 大点干!早点散----------ELK企业日志分析系统理论+实战!
- 面试题系列第8篇:谈谈String、StringBuffer、StringBuilder的区别?
- HTTP协议的请求与数据抓包
- Ubuntu 18.04 LTS 通过 Netplan 配置网络教程
- 【kafka源码】kafka内部的一些术语
- TKE使用自建NFS持久化存储
- 网站 SSL 检测 PCI DSS 不合规解决办法