如何用云开发高效快捷地实现短信验证码登录?
发布于 4 年前 作者 cuifang 1530 次浏览 来自 分享

云开发扩展能力之短信验证码登录

短信验证码登录支持在客户端使用短信验证码进行登录,封装了短信验证码的生成、发送、校验和定时清理逻辑,帮助开发者进行鉴权。登录成功后,用户身份将转化为正式用户。

本次实战我们将使用web云开发实现短信验证码登录并新增数据。

资源准备

  • 云开发环境
  • 腾讯云短信服务
  • 短信验证码登录扩展能力
  • 静态网站托管

一、云开发环境开通

如果已有云环境,可直接跳过这一步

打开云开发控制台新建云环境:

打开云开发 CloudBase 控制台,打开左侧菜单里的__数据库__,点击__添加集合__,新增一个test集合用于新增数据测试。

二、腾讯云短信服务

  1. 开通短信服务

登录腾讯云短信控制台,这里的账号不限于小程序的账号,其他账号也可以;也不限于是个人账号还是企业账号,不过账号需要进行实名认证,个人认证用户只能发送短信验证码、短信通知等,不能用于营销短信;企业认证用户可以发送短信验证码、短信通知、营销短信等。如果账号已经认证,直接申请短信服务就可以开通了。

  1. 创建签名和正文模板

国内短信由签名+正文组成,签名符号为【】,发送短信内容时必须带签名。所以要发送短信,需要申请短信签名和正文模板,两者都通过审核后,就可以开始发送短信了。

创建签名

打开左侧菜单里的__国内短信__-签名管理,点击__创建签名__,创建完签名后,这个签名内容之后会用到。

  • 签名用途:选择【自用(签名为本账号实名认证的公司、网站、产品名等)】。
  • 签名类型:选择【公众号】。
  • 签名内容:输入公司名或小程序名或公众号名或产品名称
  • 证明类型:选择公众号设置页面截图,然后上传小程序__设置页面__截图,可以参考案例;

创建正文模板

打开左侧菜单里的__国内短信__-正文模板管理,点击__创建正文模板__,创建完模板后,会有一个模板ID,这个之后会用到,也要记住你模板的变量位置。

  • 模板名称,建议带有明确目的的名称,比如“注册通知”、“购买成功反馈”等;
  • 短信类型:选择【普通短信】
  • 短信内容:比如“您正在申请手机注册,验证码为:{1},{2}分钟内有效!”,这里的{1}{2}是你要在代码里传入的变量,变量的编码必须是从{1}开始,传入变量时也要按照顺序传入

三、短信验证码登录扩展能力

打开云开发 CloudBase 控制台,打开左侧菜单里的__扩展能力__,点击__短信验证码登录__模块进行安装。

该扩展会创建以下云资源:

云函数

  • tcb-sms-auth
    生成校验码并发送到指定手机号,以实现短信验证码登录

云数据库

  • tcb-sms-auth
    存储验证码相关信息。

根据提示完成配置和安装。

四、开通静态网站托管

云开发为开发者提供静态网页托管的能力,静态资源(HTML、CSS、JavaScript、字体等)的分发由对象存储 COS 和拥有多个边缘网点的 CDN 提供支持。您可在腾讯云控制台进行静态网站的部署,提供给您的用户访问。

打开云开发 CloudBase 控制台,打开左侧菜单里的__静态网站托管__,点击__开启使用__,然后等待几分钟便可初始化完成。

使用扩展

在 web 网站使用该扩展,请先在 云开发控制台 将网站域名添加为当前环境的安全域名。

打开云开发 CloudBase 控制台,复制__静态网站托管__-基础配置__里的默认域名,然后打开左侧菜单里的__环境-安全配置,将默认域名添加为__WEB安全域名__。

一、使用方法

  1. 安装扩展 SDK 到项目
  • 方法一:通过包管理器引入
npm install --save @cloudbase/extension-sms
  • 方法二:通过CDN引入
<script src="//unpkg.com/@cloudbase/extension-sms/built/index.umd.js">script>
  1. 调用扩展 SDK

调用参数

名称 类型 是否必须 说明
action String 操作类型,支持 Send 和 Login
phone String 电话号码
app Tcb tcb实例
smsCode String 短信验证码,action 为 Login 时需要传入
customDomain String HTTP触发的自定义域名

返回内容

目前两种 action 都没有返回值。(本例采用 auth.hasLoginState() 来判断登录 )

二、编写代码

写了一个简单的demo来实现登录并新增数据功能,代码如下:

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>

<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; }

	<span class="hljs-selector-class">.modal\_content</span> {
		<span class="hljs-attribute">padding</span>: <span class="hljs-number">30px</span>;
		<span class="hljs-attribute">display</span>: flex;
		<span class="hljs-attribute">justify-content</span>: center;
		<span class="hljs-attribute">flex-direction</span>: column;
	}

	<span class="hljs-selector-class">.modal\_content</span>&gt;<span class="hljs-selector-tag">div</span> {
		<span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">20px</span>;
	}

	<span class="hljs-selector-class">.modal\_content</span>&gt;<span class="hljs-selector-tag">h5</span><span class="hljs-selector-pseudo">:first-child</span> {
		<span class="hljs-attribute">margin</span>: <span class="hljs-number">30px</span> <span class="hljs-number">0px</span>;
	}

	<span class="hljs-selector-id">\#dialog</span> <span class="hljs-selector-tag">label</span> {
		<span class="hljs-attribute">color</span>: <span class="hljs-number">\#666</span>;
	}

	<span class="hljs-selector-id">\#phone1</span> {
		<span class="hljs-attribute">display</span>: block;
		<span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
		<span class="hljs-attribute">height</span>: <span class="hljs-number">70px</span>;
		<span class="hljs-attribute">background</span>: none;
		<span class="hljs-attribute">padding-top</span>: <span class="hljs-number">30px</span>;
		<span class="hljs-attribute">border</span>: <span class="hljs-number">0</span>;
		<span class="hljs-attribute">outline</span>: none;
		<span class="hljs-attribute">text-align</span>: center;
		<span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">30px</span>;
		<span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
		<span class="hljs-attribute">border-bottom</span>: <span class="hljs-number">1px</span> solid <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, .<span class="hljs-number">2</span>);
		<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">0</span>;
	}

	<span class="hljs-selector-class">.code1</span> {
		<span class="hljs-attribute">display</span>: flex;
		<span class="hljs-attribute">flex-direction</span>: row;
		<span class="hljs-attribute">justify-content</span>: space-between;
		<span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
		<span class="hljs-attribute">height</span>: <span class="hljs-number">70px</span>;
		<span class="hljs-attribute">background</span>: none;
		<span class="hljs-attribute">padding-top</span>: <span class="hljs-number">30px</span>;
		<span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">30px</span>;
		<span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
		<span class="hljs-attribute">border-bottom</span>: <span class="hljs-number">1px</span> solid <span class="hljs-built_in">rgba</span>(<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, .<span class="hljs-number">2</span>);
		<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">0</span>;
	}

	<span class="hljs-selector-id">\#code1</span> {
		<span class="hljs-attribute">width</span>: <span class="hljs-built_in">calc</span>(<span class="hljs-number">100%</span> - <span class="hljs-number">90px</span>);
		<span class="hljs-attribute">height</span>: <span class="hljs-number">55px</span>;
		<span class="hljs-attribute">background</span>: none;
		<span class="hljs-attribute">padding-top</span>: <span class="hljs-number">20px</span>;
		<span class="hljs-attribute">border</span>: <span class="hljs-number">0</span>;
		<span class="hljs-attribute">outline</span>: none;
		<span class="hljs-attribute">text-align</span>: center;
		<span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">20px</span>;
		<span class="hljs-attribute">font-size</span>: <span class="hljs-number">16px</span>;
	}

	<span class="hljs-selector-id">\#btnSendCode1</span> {
		<span class="hljs-attribute">width</span>: <span class="hljs-number">90px</span>;
		<span class="hljs-attribute">height</span>: <span class="hljs-number">30px</span>;
		<span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">5px</span>;
		<span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
		<span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
		<span class="hljs-attribute">text-align</span>: center;
		<span class="hljs-attribute">background</span>: transparent;
		<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">30px</span>;
		<span class="hljs-attribute">color</span>: <span class="hljs-number">\#a07941</span>;
		<span class="hljs-attribute">border-color</span>: <span class="hljs-number">\#a07941</span>;

	}

	<span class="hljs-selector-pseudo">::-webkit-input-placeholder</span> {
		<span class="hljs-comment">/\* WebKit browsers \*/</span>

font-size: 14px; color: rgba(0, 0, 0, .4); }

	<span class="hljs-selector-pseudo">:-moz-placeholder</span> {
		<span class="hljs-comment">/\* Mozilla Firefox 4 to 18 \*/</span>

font-size: 14px; color: rgba(0, 0, 0, .4); }

	<span class="hljs-selector-pseudo">::-moz-placeholder</span> {
		<span class="hljs-comment">/\* Mozilla Firefox 19+ \*/</span>

font-size: 14px; color: rgba(0, 0, 0, .4); }

	<span class="hljs-selector-pseudo">:-ms-input-placeholder</span> {
		<span class="hljs-comment">/\* Internet Explorer 10+ \*/</span>

font-size: 14px; color: rgba(0, 0, 0, .4); }

	<span class="hljs-selector-class">.next</span> {
		<span class="hljs-attribute">text-align</span>: center;
		<span class="hljs-attribute">margin</span>: <span class="hljs-number">20px</span> <span class="hljs-number">0</span>;
	}

	<span class="hljs-selector-class">.next</span> <span class="hljs-selector-tag">button</span> {
		<span class="hljs-attribute">width</span>: <span class="hljs-number">100%</span>;
		<span class="hljs-attribute">height</span>: <span class="hljs-number">45px</span>;
		<span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
		<span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
		<span class="hljs-attribute">background</span>: <span class="hljs-number">\#007BFF</span>;
		<span class="hljs-attribute">color</span>: <span class="hljs-number">\#fff</span>;
		<span class="hljs-attribute">border</span>: <span class="hljs-number">0</span>;
		<span class="hljs-attribute">outline</span>: none;
		<span class="hljs-attribute">border-radius</span>: <span class="hljs-number">3px</span>;
	}
	
	<span class="hljs-selector-class">.content2</span>{
		<span class="hljs-attribute">display</span>:none;
	}
</span><span class="hljs-tag"><!--<span class="hljs-name"-->style</span>&gt;

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}$)|(^09\d{8}$)/;//手机号正则 var count = 60; //间隔函数,1秒执行 var InterValObj1; //timer变量,控制时间 var curCount1;//当前剩余秒数 function islogin(){ if (auth.hasLoginState()) { // 此时已经登录 $(".content1").hide(); $(".content2").show(); return true; } return false; }

	<span class="hljs-comment">/\*第一\*/</span>

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)); } }

	<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">SetRemainTime1</span>(<span class="hljs-params"></span>) </span>{
		<span class="hljs-keyword">if</span> (curCount1 == <span class="hljs-number">0</span>) {
			<span class="hljs-built_in">window</span>.clearInterval(InterValObj1);<span class="hljs-comment">//停止计时器</span>
			$(<span class="hljs-string">"\#btnSendCode1"</span>).removeAttr(<span class="hljs-string">"disabled"</span>);<span class="hljs-comment">//启用按钮</span>
			$(<span class="hljs-string">"\#btnSendCode1"</span>).val(<span class="hljs-string">"重新发送"</span>);
		}
		<span class="hljs-keyword">else</span> {
			curCount1--;
			$(<span class="hljs-string">"\#btnSendCode1"</span>).val(+ curCount1 + <span class="hljs-string">"秒再获取"</span>);
		}
	}

	<span class="hljs-comment">/\*提交\*/</span>

async function binding() { var phone = $.trim($(’#phone1’).val()); var smsCode = $.trim($(’#code1’).val()); try { await tcb.invokeExtension(extSms.name, { action: ‘Login’, app, phone, smsCode, });

		} <span class="hljs-keyword">catch</span> (err) {
			<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(err, <span class="hljs-literal">null</span>, <span class="hljs-number">4</span>));
		} <span class="hljs-keyword">finally</span> {
			<span class="hljs-comment">//无论try catch结果如何还是继续执行</span>

if(islogin()){ alert(“登录成功,目前是正式用户”); }else{ alert(“登录失败,请检查验证码”); } } }

	<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">add</span>(<span class="hljs-params"></span>) </span>{
		<span class="hljs-keyword">try</span> {
			<span class="hljs-keyword">var</span> text = $.trim($(<span class="hljs-string">'\#text1'</span>).val());
			<span class="hljs-keyword">await</span> db.collection(<span class="hljs-string">"test"</span>).add({
				<span class="hljs-attr">text</span>:text
			}).then(<span class="hljs-function"><span class="hljs-params">res</span> =&gt;</span> {
				alert(<span class="hljs-string">"数据新增成功"</span>);
				<span class="hljs-built_in">console</span>.log(res);
			})
			.catch(<span class="hljs-function"><span class="hljs-params">e</span> =&gt;</span> {
				alert(<span class="hljs-string">"数据新增失败"</span>);
				<span class="hljs-built_in">console</span>.log(e);
			});
		} <span class="hljs-keyword">catch</span> (err) {
			<span class="hljs-built_in">console</span>.log(<span class="hljs-built_in">JSON</span>.stringify(err, <span class="hljs-literal">null</span>, <span class="hljs-number">4</span>));
		} 
	}
</span><span class="hljs-tag"><!--<span class="hljs-name"-->script</span>&gt;

body> html>

三、上传部署

完成demo编写后,将代码上传至__静态网站托管__,完成部署。

  • 控制台上传

打开云开发 CloudBase 控制台,打开左侧菜单里的__静态网站托管__,将刚刚编写的文件sms.html上传。

  • CLI 工具上传

CloudBase CLI 是一个开源的命令行界面交互工具,用于帮助用户快速、方便的部署项目,管理云开发资源。具体安装步骤和使用方法可以访问云开发 CLI 工具文档进行查看。

效果展示

  • 发送短信

  • 登录验证

  • 新增数据

总结

通过上述步骤,利用云开发提供的短信验证码登录扩展能力,配合云开发的SDK在web端很方便的实现了自定义登录并新增数据,大家快去试试吧!

2 回复

云开发确实挺好用

回到顶部