如何用Python和Twilio验证你在WhatsApp上的用户

382 阅读8分钟

Twilio Verify是一项易于使用的服务,通过数字代码进行用户验证。这项服务现在包括对WhatsApp的支持(截至2022年6月,处于公开测试阶段)。在本教程中,你将学习如何在Python和Flask应用程序中实现WhatsApp用户验证流程。

Verification code sent to WhatsApp

要求

要完成本教程,你需要以下物品。

创建一个Twilio Verify服务

要在一个应用程序中使用Twilio Verify,必须先创建一个Verify服务。在你的网页浏览器中打开Twilio控制台,在导航栏的搜索框中输入verify,并在搜索结果中选择 "Verify服务"。

Verify Services in Twilio Console

在验证服务页面,点击 "立即创建服务 "按钮。

如果你的账户中已经有一个或多个Verify服务,那么这个按钮将在服务列表的顶部显示为一个加号。

在 "友好名称 "栏中输入你的应用程序的名称。在本教程中,我将使用 "Awesome App "的名称。你在这个字段中输入的名字将出现在发送给用户的WhatsApp验证信息中。一旦你输入了名字,按 "创建"。

Create new verify service

一旦服务被创建,您将被重定向到其设置页面。在您继续学习本教程时,请打开该页面,因为您以后将需要分配给您的服务的 "服务SID"。

在本教程中,服务的默认设置是合适的,但请注意你如何配置,除其他外,在发送给用户的验证码中使用多少个数字。

项目设置

在本节中,你将设置一个全新的Flask项目。为了使事情井井有条,请打开终端或命令提示符,找到一个合适的父目录,将你将要创建的项目放在那里。输入以下命令,为这个项目创建一个目录。

mkdir flask-whatsapp-verify
cd flask-whatsapp-verify

这个应用程序将需要一些HTML模板。在该项目中为它们创建一个目录。

mkdir templates

创建一个虚拟环境

按照Python的最佳实践,你现在要创建一个虚拟环境,在那里安装本项目所需的Python依赖项。

如果你使用的是 UNIX 或 macOS 系统,打开一个终端,输入以下命令。

python3 -m venv venv
source venv/bin/activate

如果你在Windows上学习本教程,在命令提示符窗口中输入以下命令。

python -m venv venv
venv\Scripts\activate

激活了虚拟环境后,就可以安装本项目所需的 Python 依赖项了。

pip install flask python-dotenv twilio

本项目使用的Python包是。

定义应用程序的设置

为了用Twilio Verify发送验证信息,Flask应用程序需要用你的Twilio账户凭证进行验证。该应用程序还需要知道分配给你上面创建的Verify服务的 "服务SID"。

定义这些配置值的最安全的方法是为它们设置环境变量,而在Flask应用程序中管理环境变量的最方便的方法是使用*.env*文件。

在你项目的根目录下创建一个名为*.env*的新文件(注意前面的点),并在其中输入以下内容。

TWILIO_ACCOUNT_SID=xxxxxxxxx
TWILIO_AUTH_TOKEN=xxxxxxxxx
TWILIO_VERIFY_SERVICE=xxxxxxxxx

你需要把所有的xxxxxxxxx 占位符替换成适用于你的正确值。前两个变量是你的Twilio "账户SID "和你的 "Auth Token"。你可以在Twilio Console主仪表板的 "账户信息 "部分找到它们。

Twilio Account Info

第三个配置变量的值来自验证服务页面的 "服务SID "字段。这是一长串以字母VA 开始的字符。

发送一个验证码

现在你已经准备好开始对 Python 应用程序进行编码。在你的文本编辑器或IDE中,在项目的根目录下创建一个名为app.py的文件。将以下内容复制到其中。

import os
from flask import Flask, render_template, request, session, redirect, url_for
from twilio.rest import Client

app = Flask(__name__)
app.config['SECRET_KEY'] = 'top-secret!'
client = Client()


@app.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'GET':
        return render_template('index.html')
    phone = request.form.get('phone')
    if not phone:
        return redirect(url_for('index'))

    verification = client.verify.services(
        os.environ['TWILIO_VERIFY_SERVICE']).verifications.create(
            to=phone, channel='whatsapp')
    if verification.status != 'pending':
        return redirect(url_for('index'))

    session['phone'] = phone
    return redirect(url_for('verify'))

该应用程序创建了两个全局对象:Flask应用程序和Twilio客户端实例。Flask应用程序实例被配置了一个密匙,因为这需要访问会话存储

Twilio客户端被隐含地初始化为环境中定义的TWILIO_ACCOUNT_SIDTWILIO_AUTH_TOKEN 变量。如果这些变量没有定义或不正确,在使用应用程序时将出现认证错误信息。

index() 函数是应用程序的根URL的处理程序。这个路由支持GETPOST 方法。GET 请求将呈现一个网页表单,用户可以在其中输入他们的WhatsApp电话号码。然后,当用户提交表单时,浏览器将向同一URL发送一个POST 请求。

当请求方法是GET ,应用程序会渲染一个名为index.html的模板。在templates子目录下创建index.html文件,并将以下HTML复制到其中。

<!doctype html>
<html>
  <head>
    <title>Twilio WhatsApp Verification Example</title>
  </head>
  <body>
    <h1>Twilio WhatsApp Verification Example</h1>
    <form method="post">
      <label for="phone">Your WhatsApp number:</label>
      <input name="phone" id="phone" placeholder="+12345678900" autofocus>
      <input type="submit" value="Submit">
    </form>
  </body>
</html>

这个HTML页面渲染了一个表单,提示用户输入他们的WhatsApp电话号码。

当用户提交表格时,浏览器将发送一个POST 请求到同一个URL。在这一点上,应用程序将从Flask框架提供的request.form 对象中获取电话号码。如果电话号码不存在,就会发出一个重定向到索引页,给用户另一个机会输入正确的信息。

然后,Twilio客户端被用来创建一个verification 实例,用用户的电话号码初始化,通道设置为whatsapp 。这将触发Twilio生成的验证码,并通过WhatsApp发送至用户提供的号码。

然后应用程序检查验证实例上的报告状态。如果状态不是pending ,就会认为发生了错误,然后用户会被重定向到主页面。

对于一个待定的验证,电话号码被存储在用户的会话中,然后用户被重定向到*/verify*URL,这就是请求验证码的地方。

验证码

一旦用户提供了一个电话号码并发出了一个验证码,应用程序的*/验证*页面允许用户输入他们通过WhatsApp收到的代码。

下面你可以看到应用程序的验证路线。在app.py的底部添加这段代码。

@app.route('/verify', methods=['GET', 'POST'])
def verify():
    if request.method == 'GET':
        return render_template('verify.html')
    phone = session.get('phone')
    code = request.form.get('code')
    if not phone:
        return redirect(url_for('index'))
    if not code:
        return redirect(url_for('verify'))
        
    verification_check = client.verify.services(
        os.environ['TWILIO_VERIFY_SERVICE']).verification_checks.create(
            to=phone, code=code)
    if verification_check.status == 'approved':
        del session['phone']
        return redirect(url_for('success'))
    return redirect(url_for('verify'))

这个路由也支持GETPOST 请求。在GET 的情况下,它渲染一个名为verify.html的模板。在你的编辑器中,在模板子目录下打开一个名为verify.html的新文件,并复制以下HTML页面到其中。

<!doctype html>
<html>
  <head>
    <title>Twilio WhatsApp Verification Example</title>
  </head>
  <body>
    <h1>Twilio WhatsApp Verification Example</h1>
    <form method="post">
      <label for="code">Verification code:</label>
      <input name="code" id="code" placeholder="123456" autofocus>
      <input type="submit" value="Submit">
    </form>
  </body>
</html>

verify.html中定义的表单要求用户提供一个代码。当表单被提交时,一个POST 的请求被发送到同一个URL。

应用程序从会话存储中检索phone 参数和随表单提交的code 参数,并将它们发送给 Twilio Verify 以创建一个验证检查实例。如果代码对给定的号码是正确的,那么验证检查的状态是approved 。在这种情况下,电话号码从会话中删除,然后用户被重定向到*/successURL上的应用程序的第三个也是最后一个路径。如果状态是任何其他的值,那么验证就失败了,用户会被重定向到/verify*路线,尝试另一个代码。

下面,你可以看到*/success路由的定义。把这段代码复制到app.py*的底部。

@app.route('/success')
def success():
    return render_template('success.html')

这个路由除了渲染一个success.html模板外,不需要任何逻辑。这个HTML模板如下图所示。记住,模板文件要放在templates子目录下。

<!doctype html>
<html>
  <head>
    <title>Twilio WhatsApp Verification Example</title>
  </head>
  <body>
    <h1>Twilio WhatsApp Verification Example</h1>
    <p>You have been verified!</p>
    <p><a href="/">Verify another number?</a></p>
  </body>
</html>

运行应用程序

现在应用程序已经完成了。确保你的app.py文件在项目的根目录下,并且你的templates子目录中有index.htmlverify.htmlsuccess.html文件。

在你的终端输入以下命令来启动应用程序。

flask run

一旦应用程序启动,打开您的网络浏览器并导航到*http://localhost:5000。*以E.164格式键入你的WhatsApp电话号码,以请求一个验证码。

几秒钟后,您应该在WhatsApp上收到一条带有您的代码的信息。在应用程序的验证页面中输入这个代码,就会收到一个成功的消息。此外,请随时尝试一个错误的代码,看看它是如何被拒绝的,你会得到另一个机会。

Flask application demo

结论

恭喜你学会了如何用Twilio Verify验证WhatsApp上的用户!你知道Twilio Verify也可以通过短信、语音电话和电子邮件向用户发送验证码吗?它还可以验证标准的TOTP代码和推送通知到你的iOS或Android应用程序

我很想看看你用Twilio Verify建立了什么!

*Miguel Grinberg*是Twilio的技术内容首席软件工程师。与他联系的方式是 mgrinberg *[at] twilio [dot] com联系他。*如果你有一个很酷的项目想在这个博客上分享,请联系他。