在本教程中,你将学习如何在Django中使用Twilio制作一个一次性密码(OTP)验证系统。这个应用将允许用户选择他们喜欢的方式来接收OTP。
我们将使用Twilio短信服务和Twilio WhatsApp沙盒,通过短信和WhatsApp渠道向用户传递OTP。
让我们来谈谈本教程的主要重点。
我们的主要重点是建立一个传递OTP和验证的管道。这就是我们今天要做的全部。
我们不打算做什么呢?
我们不会使用默认的Django登录设置来制作整个Django用户管理和认证系统--我们将简单地使用cookies来查看用户是否经过OTP验证。
记住这些事情,让我们开始吧。
前提条件
- 安装了Python3.6或以上版本
- Django的基本知识(你将有机会在后面的步骤中安装它。)
- 一个Twilio账户 (如果你没有,可以在这里注册一个免费账户。)
- 一个用于测试的电话号码和WhatsApp号码
设置
首先,导航到你想建立项目的地方,并创建一个新的目录,该项目中的所有文件都将在此存放。一旦你完成了这项工作,请切换到新的目录。
mkdir twiliotutorial
cd twiliotutorial
接下来,你需要创建一个Python虚拟环境,在那里你可以安装这个项目的依赖项。如果你在 Mac 或 Unix 环境中工作,运行下面的命令。
python3 -m venv venv
source venv/bin/activate
如果你在 Windows 环境下工作,请运行下面的命令。
python -m venv venv
venv\Scripts\activate
在这个新的虚拟环境中,安装这个项目的依赖项。
pip3 install django twilio
现在你有了你需要的需求,是时候开始构建我们的项目了。
创建一个空白的Django项目
让我们开始创建一个带有单个应用程序的基本Django项目。在终端运行以下命令来创建新的Django项目。
django-admin startproject twiliotutorial
这将创建一个空白项目。现在,切换到项目目录,并运行以下命令,创建一个简单的Django应用程序,名为验证。
python manage.py startapp verification
打开twiliotutorial/settings.py,将verification 加入到应用列表中。
.....
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'verification'
]
......
现在转到twiliotutorial/urls.py并包括该应用的 urls。
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
path('admin/', admin.site.urls),
path('',include('verification.urls'),name="verification")
]
在验证文件夹内,创建一个名为urls.py的新文件并添加以下代码。
from django.urls import path
from . import views
urlpatterns = [
path('', views.register, name='register'),
path('home', views.home, name='home'),
path('otp/<str:uid>/', views.otpVerify, name='otp')
]
我们将为我们的项目使用三个视图。一个是用于注册的,它将接受你的用户名和电话号码,然后它将向你的电话号码发送一个OTP。
OTP验证端点是你将能够输入你的OTP进行验证,最后,如果你在10分钟内输入正确的OTP,你将被重定向到主页端点。
现在去验证/views.py,做3个占位符函数。
from django.http import HttpResponse
from django.shortcuts import render,redirect
from django.contrib.auth.models import User
from .models import Profile
import random
from .helper import MessageHandler
def home(request):
pass
def register(request):
pass
def otpVerify(request,uid):
pass
现在,对于设置Django项目的最后一步,让我们创建一个模型,用于保存用户资料和在资料中保存OTP。转到验证/models.py,添加这段代码。
from django.db import models
from django.contrib.auth.models import User
import uuid
# Create your models here.
class Profile(models.Model):
user=models.OneToOneField(User, on_delete=models.CASCADE,related_name="profile")
phone_number=models.CharField(max_length=15)
otp=models.CharField(max_length=100,null=True,blank=True)
uid=models.CharField(default=f'{uuid.uuid4}',max_length=200)
这里我们要创建一个简单的配置文件模型,它有一个与默认的Django用户模型的链接字段。还有一个字段,将包含用户的电话号码。
OTP字段将存储最近发送给与档案相关的用户的OTP,UID字段将用于获取某个档案对象。
现在你已经全部完成了Django项目的基本结构的设置,你可以通过在终端运行以下命令来运行必要的迁移并启动服务器。
python manage.py makemigrations
python manage.py migrate
python manage.py runserver
为短信设置Twilio
如果你是Twilio的新手,请到www.twilio.com/try-twilio,如果你还没有一个免费账户,请创建一个免费账户。
然后验证你自己的电话号码。
选择你喜欢的设置。
然后你会看到类似下面的内容。 点击 "获得一个Twilio电话号码"。

完成账户设置步骤后,你会在Twilio控制台中看到以下细节,你将在Django项目中使用。
将它们添加到twiliotutorial/settings.py的底部。
ACCOUNT_SID='YOUR ACCOUNT SID'
AUTH_TOKEN='YOUR AUTH TOKEN'
COUNTRY_CODE='+country code of your choice'
TWILIO_WHATSAPP_NUMBER='whatsapp:+14155238886'
TWILIO_PHONE_NUMBER='number you get from Twilio'
在本教程中,设置中加入了一个国家代码,这样短信或WhatsApp信息就只能发送到你所选国家内的号码。
如果你对发送国际信息感兴趣,你可以自定义代码,删除对国家代码的引用,并在后面的测试步骤中,让用户以国际E.164格式输入他们的电话号码。
设置Twilio用于WhatsApp信息传递
对于WhatsApp消息,我们将需要设置一个Twilio WhatsApp沙盒。它的工作原理是这样的:我们将从我们的程序发送消息到Twilio服务器,然后Twilio将发送消息到我们注册的WhatsApp号码。
在左边的侧边栏,在信息菜单下,进入 "试用",然后 "发送WhatsApp信息"。
在Twilio沙盒页面,点击蓝色链接,上面写着 "点击这里"。然后发送一条包含粗体字突出显示的文本的WhatsApp信息(你的信息可能有所不同),以注册你的电话号码,以便在开发环境中接收WhatsApp信息。
如果您看到这条消息,这意味着您的号码已经准备好接收WhatsApp信息。请记住,只有当你想在沙盒环境中开发应用程序时,你才需要验证号码。
创建Django和Twilio之间的连接
为了创建连接,我们将使用一个帮助文件来发送WhatsApp和SMS消息。
在验证文件夹中创建一个名为helper.py的新文件。
我们将在该文件中创建一个MessageHandler ,该类将负责发送WhatsApp和短信。将代码添加到该文件中,如下所示。
from django.conf import settings
from twilio.rest import Client
class MessageHandler:
phone_number=None
otp=None
def __init__(self,phone_number,otp) -> None:
self.phone_number=phone_number
self.otp=otp
def send_otp_via_message(self):
client= Client(settings.ACCOUNT_SID,settings.AUTH_TOKEN)
message=client.messages.create(body=f'your otp is:{self.otp}',from_=f'{settings.TWILIO_PHONE_NUMBER}",to=f'{settings.COUNTRY_CODE}{self.phone_number}')
def send_otp_via_whatsapp(self):
client= Client(settings.ACCOUNT_SID,settings.AUTH_TOKEN)
message=client.messages.create(body=f'your otp is:{self.otp}',from_=f'{settings.TWILIO_WHATSAPP_NUMBER}',to=f'whatsapp:{settings.COUNTRY_CODE}{self.phone_number}')
你可以按原样使用上述代码,但为了你的好奇心,让我解释一下这段代码。我们创建一个MessageHandler 类,它需要两个参数:OTP 和phone_number 。phone_number 是我们要发送OTP的电话号码。
我们在这个类中有两个函数:一个负责发送短信,另一个负责发送WhatsApp信息。
我们先在这两个函数中初始化Client ,然后使用Twilio函数发送消息。注意,在WhatsApp函数中,我们将使用一个沙盒电话号码,而不是Twilio给我们的号码。
为你的项目创建前端
在本节中,我们将创建register 和otpVerify 视图,以及它们的HTML文件。
创建register 视图
让我们为我们的HTML文件编写代码。在验证应用程序的文件夹中,创建一个名为templates的新文件夹,并在里面创建一个名为register**.html的文件。
添加以下代码。
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
<style>
body{
background-color: rgb(193, 156, 228);
}
form {
position: fixed; /* Stay in place */
left: 30%;
top: 10%;
width: 300px; /* Full width */
height: 350px; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(55, 56, 95); /* Fallback color */
padding: 60px;
color: aliceblue;
}
input[type=text], input[type=password] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
input[type=submit]{
margin-top:50px;
width:100px;
height:50px;
font-size: 20px;
border-radius: 20px;
background-color: rgb(33, 70, 70);
color: wheat;
}
.radio-box{
margin-top:-30px;
}
h2{
margin-top: -30px;
color: rgb(213, 217, 221);
}
</style>
</head>
<body>
<form action="/" method="post">
<h2>REGISTRATION FORM</h2>
{% csrf_token %}
<label for="user_name">User name:</label>
<input id="user_name" type="text" name="user_name">
<br>
<label for="phone_number">Phone Number:</label>
<input id="phone_number" type="text" name="phone_number">
<br>
<h3>OTP verification method:</h3>
<br>
<div class="radio-box">
<label for="methodOtpSms">SMS:</label>
<input type="radio" name="methodOtp" id="methodOtpSms" value="methodOtpSms">
<label for="methodOtpWhatsapp">WhatsApp:</label>
<input type="radio" name="methodOtp" id="methodOtpWhatsapp" value="methodOtpWhatsapp">
</div>
<input type="submit" value="login">
</form>
</body>
</html>
在这里,用户可以简单地填写表格,然后提交,发送一个POST请求。这个表单允许他们在输入框中输入他们的用户名和电话号码,并使用单选按钮来选择他们是否要从短信或WhatsApp接收OTP。
现在在verification/views.py中*,*让我们做一个注册视图。
def register(request):
if request.method=="POST":
if User.objects.filter(username__iexact=request.POST['user_name']).exists():
return HttpResponse("User already exists")
user=User.objects.create(username=request.POST['user_name'])
otp=random.randint(1000,9999)
profile=Profile.objects.create(user=user,phone_number=request.POST['phone_number'],otp=f'{otp}')
if request.POST['methodOtp']=="methodOtpWhatsapp":
messagehandler=MessageHandler(request.POST['phone_number'],otp).send_otp_via_whatsapp()
else:
messagehandler=MessageHandler(request.POST['phone_number'],otp).send_otp_via_message()
red=redirect(f'otp/{profile.uid}/')
red.set_cookie("can_otp_enter",True,max_age=600)
return red
return render(request, 'register.html')
在这里,我们在GET请求中渲染register.html,在POST请求中,我们首先用用户名创建一个用户对象(如果它不存在的话),然后我们用randint 函数生成一个OTP。
然后我们用之前创建的user 实例、电话号码和OTP创建一个Profile 。
之后,我们检查用户选择什么方式来接收他们的OTP,并使用我们之前创建的函数发送OTP。
最后,我们设置一个有效期为10分钟的cookie,我们将使用这个cookie来定义输入OTP的时间限制。
这里是前台的样子。
在你的服务器仍在运行的情况下,你可以通过在浏览器中打开http://localhost:8000/,看到这个表单。
验证OTP并重定向到主页
在这一部分,我们将创建主要功能--本教程的重点:我们将使用直接的逻辑来验证OTP。
在模板文件夹中创建一个文件,命名为otp.html。
转到otp.html并添加这段代码。
<!DOCTYPE html>
<html>
<head>
<title>Register</title>
<style>
body{
background-color: rgb(193, 156, 228);
}
form {
position: fixed; /* Stay in place */
left: 30%;
top: 10%;
width: 300px; /* Full width */
height: 200px; /* Full height */
overflow: auto; /* Enable scroll if needed */
background-color: rgb(55, 56, 95); /* Fallback color */
padding: 60px;
color: aliceblue;
}
input[type=text], input[type=password] {
width: 100%;
padding: 12px 20px;
margin: 8px 0;
display: inline-block;
border: 1px solid #ccc;
box-sizing: border-box;
}
input[type=submit]{
margin-top:50px;
width:100px;
height:50px;
font-size: 20px;
border-radius: 20px;
background-color: rgb(33, 70, 70);
color: wheat;
}
.radio-box{
margin-top:-30px;
}
h2{
margin-top: -30px;
margin-left: 30px;
color: rgb(213, 217, 221);
}
</style>
</head>
<body>
{% block includes %}
<form action="/otp/{{id}}/" method="post">
<h2>OTP VERIFICATION:</h2>
{% csrf_token %}
<label for="otp">OTP: </label>
<input id="otp" type="text" name="otp">
<input type="submit" value="login">
</form>
{% endblock includes %}
</body>
</html>
在这里,我们只是从用户那里获取OTP,并将其送回otp/<uid> 端点。这里,{{id}} 将从我们将创建的视图中发送。
下面是它的外观。
转到verification/views.py并创建otpVerify 函数。
def otpVerify(request,uid):
if request.method=="POST":
profile=Profile.objects.get(uid=uid)
if request.COOKIES.get('can_otp_enter')!=None:
if(profile.otp==request.POST['otp']):
red=redirect("home")
red.set_cookie('verified',True)
return red
return HttpResponse("wrong otp")
return HttpResponse("10 minutes passed")
return render(request,"otp.html",{'id':uid})
在这里,我们将OTP.html和uid 一起呈现给GET请求。对于POST请求,我们首先检查我们创建的cookie是否仍然有效。如果不是,那么我们将得到一个信息,即10分钟已经过去了。
然后,我们使用uid ,以获得用户的个人资料,并检查保存在个人资料上的OTP是否与用户输入的OTP相符。如果匹配,那么我们就将cookies设置为verified=True ,并将用户重定向到主页。否则,verified=False ,然后应用程序将重定向到主页。
最后,让我们来创建主页视图。
def home(request):
if request.COOKIES.get('verified') and request.COOKIES.get('verified')!=None:
return HttpResponse(" verified.")
else:
return HttpResponse(" Not verified.")
这个视图将检查验证cookie是否被设置为真,它将在此基础上返回一个响应。
测试你的工作
确保你已经验证了你要用来测试的号码。如果你还没有这样做,在这里验证你的电话号码。
我们将使用我们用来验证Twilio账户的电话号码来接收OTP。
以下是一切的工作方式。
输入一个用户名和电话号码,然后选择OTP验证方法。
一旦你在手机上收到了OTP,就把这个号码输入到验证表格中。
验证OTP后,你会看到一个页面,上面有HTTPResponse "已验证"。
这里是我们通过短信收到的OTP。
如果你选择WhatsApp,OTP将看起来像下面这样。
总结
我们今天学到了什么?
- 如何为Django网站创建你自己的验证系统
- 如何让用户选择短信和WhatsApp来接收OTP
- 如何在一个应用程序中使用短信或WhatsApp进行认证
- Django中OTP认证的管道
我是Ath Tripathi,一个来自印度的16岁的程序员,在过去的3年里,我一直在做编程,作为兼职和自由职业者为许多客户和公司工作。网络、应用程序和游戏开发是我的主要兴趣。我做博客是一种业余爱好,也是一个自由职业者。