(超详细)django+html+mysql实现手机验证码登录
至于这个验证码,网上的教程一般是存储到redis,是一个位于内存空间的轻量化数据库,和mysql相比是不限于存储在硬盘空间的,更方便,不过redis也基本上就是和程序共存亡,在程序结束的时候redis应该也就释放了。而在这里网站给你提供了一个写好的模板,也就是3部分的content,1中的每行都是不一样的API,这里我们先讲发送短信,模板后面再说,上面是两个视图函数,一个是接收手机号,另一个是进行
原文章:
(超详细)django+html+mysql实现手机验证码登录 - 知乎
此文章为作者本人搬运至该网站。
对于手机验证码验证登录这件事儿,
网上的教程总是不全,要么是只有代码,不说怎么找短信服务,要么是虽然很详细,但是就是运行不了,哎哎。
现在我可以大胆的说!这里是最详细的!!!
启发我的:
Python后端-基于Django的博客系统之增加手机验证码登录(九)_django 短信验证-CSDN博客
这里是基于django和vue还有redis来实现的,
vue是前端的大头,redis是一个简洁的内存数据库系统,比mysql更易于存储,不过也不能长久持续(可以说是跟着程序的运行来存在的)
但是对于只想用django来做的人们来说无疑是致命的,
所以这里我们用到的工具只有:
django(pycharm)、html(pycharm)、mysql(navicat),
不需要vue,JavaScript以及redis!
首先我们需要在网上找到能发送短信的云服务:
上面那个vue实现的连接,对我来说最有用的就是这个:
阿里云的云市场的短信专区!!
这里是一些第三方公司提供的API服务,跟阿里云官方的服务器相比要便宜与方便许多!

比如他们会有免费试用发送五次短信,
以及三块钱一百次短信的服务,对于咱们学习来说肯定够了。
购买或者免费试用后,我们会获得如下的信息:

其中最重要的就是这个AppCode,这相当于我们使用这个API的钥匙。

之后我们可以到这里进行查看我们的API:

到这里后我们主要注意几点:


1.我们发送短信是需要模板的(字面意义上的模板,也就是除了6位验证码之外的写好的内容),
而在这里网站给你提供了一个写好的模板,也就是3部分的content,1中的每行都是不一样的API,这里我们先讲发送短信,模板后面再说,
2.是发送请求,它和4息息相关,
也就是说我们content(短信验证码信息)中的内容以及mobile(手机号)的内容,会通过2进行发送,
3.是我们模板的内容,mobile就是我们的手机号,这里我们可以先填上自己的手机号,content就是我们的验证码,这里除了6位数字可以自己改(也就是说你可以写成114514),其他都不能改动。
4.是我们的接口API信息,包括地址,请求方式之类的,而它真正的面容是在4中的“请求示例”:

这里才是我们发送请求的实现代码的本来面目!!!
当我们填好手机号后,点击发送请求,我们的手机就会收到有关content的验证码消息:

而上面的这段代码,实际上就是我们用来在本地实现的代码,
也就是说,我们可以把上面这一段代码移植到我们pycham的python上,再进行一些修改就也可以实现法发送短信的功能!
接下来让我们细细讲来这段代码:

1.host就是我们要调用API的的网址(也就是说,在本地化运行的时候还是需要你联网才能实现)
2.appcode就是我们之前获得的AppCode,
(简单来说,host用来定位我们网上找的API的位置,appcode用来让我们有权限来使用这个API

3.query是什么呢?
各位看里面的东西!

mobile和content,
这不就是我们上张图里面3的东西嘛!

所以实际上我们这段代码中我们要发送的对象和内容都是在这个query里面的,
既然这个mobile我们知道了,那么后面那个contents为什么是一串乱码呢?
先别急!我们看下面的!

这里的decode('utf-8'),意思就是按utf-8解码,
为什么呢?
其实我们如果把它移植到本地运行后我们就可以发现了(这里我就不放出来了)
我们要把content的内容传出来的话,就需要把我们的内容用utf-8编码,
而上面query的内容:
%E3%80%90%E6%99%BA%E8%83%BD%E4%BA%91%E3%80%91%E6%82%A8%E7%9A%84%E9%AA%8C%E8%AF%81%E7%A0%81%E6%98%AF568126%E3%80%82%E5%A6%82%E9%9D%9E%E6%9C%AC%E4%BA%BA%E6%93%8D%E4%BD%9C%EF%BC%8C%E8%AF%B7%E5%BF%BD%E7%95%A5%E6%9C%AC%E7%9F%AD%E4%BF%A1
我们用utf-8解码网站解码一下:

啊哈!!!
正是我们content的内容!!!

这下就一目了然了!!!
所以这段代码:

所以这段代码我真正要注意到的地方就是:
1.host是我们调用API的网址
2.appcode改为自己的appcode;
3.querys含有我们的手机号和要发送的验证码的内容;
但是这显然不符合我们的标准啊!
如果我们要把这段代码成为一个可以随时调用的本地函数(函数再去调用API),
那么我们就不能让mobile显示在代码中,而是需要我们当作参数来引进这个函数,
同时验证码也需要我们用随机数生成,
并在最后返回出这个验证码:

我的改动就是上面的这四个红框,
第一个红框里面是把appcode改为自己的,
之后加上一个从100000到999999之间的6位数随机字符串,
用msg作为我们的content,
并把这个msg用utf-8加密,之后把6位随机字符串和这个utfmsg合并位query,作为我们的内容。
其余不改动,最后返回这个6位随机字符串验证码,让后端在调用这个函数的时候就能知道这个验证码的内容。
这样我们在本地的这个随调随用的函数就实现了!!!
也许有人会说,这么方便,那我能不能改一下msg的内容?比如改成
【哼哼哼】啊啊啊啊啊啊:114514
当然是不行的!
经过测试得知:我们的短信内容是有要求的,前面必须要加上标签,也就是那个【】的部分,
后面的内容也要有格式,
就是我们之前所说的模板。

还记得我们之前说过左边每行都是一个API吗,
这里就是我们添加模板的API,这里的每一次提交的都是我们在发送短信的API里面使用的内容,
signature就是我们的【】,
content就是我们短信里面的content,
此外需要注意的是!短信的模板不是我们随便提交就能生成的,似乎是需要经过审核
(毕竟是要直接发到别人手机里的东西嘛)
我们也可以在API里面的最后一个的模板列表里面,
通过发起请求来查看我们可以使用的模板,

这两个应该都是预设的模板,
我几个小时之前测试的时候申请的两个模板似乎还没有通过。。。。
讲到这里大家应该也就清晰了模板的作用了。
把它放到django的views.py里面:
只在自己的函数里面煽风点火肯定是不行的哒!!!
有了这个函数我觉得大家也应该能自己做出来了,
我就大致讲一下思路,然后就直接放代码了。
思路其实就是我们在登录的视图函数里面去引用这个函数,当接收到手机号(form表单提交)的时候,
就可以通过这个函数去生成一个验证码,同时发送给手机,
至于这个验证码,网上的教程一般是存储到redis,是一个位于内存空间的轻量化数据库,和mysql相比是不限于存储在硬盘空间的,更方便,不过redis也基本上就是和程序共存亡,在程序结束的时候redis应该也就释放了。
而且既然我们之前做的是mysql,而且数据也不是不能存,那就还是用数据库辣!
此外,我们还要注意的就是,验证码通常有一个几分钟的限制,过期了就不能验证了,
对此方法我们就是,在生成验证码的时候,把验证码和生成验证码的时间一并存到数据库,
等到用户输入验证码进行比对的时候,再获取一下此时的时间,
两个时间进行相减,看时间是否超时了即可。
其他应该没什么了。
接下来我就直接放代码了,保证能直接运行!(有些地方需要改我会说一下)
首先是views.py代码:
import datetime
import requests
from django.shortcuts import render, HttpResponse
from.models import User
from django.views.decorators.csrf import csrf_exempt
import random
import urllib, urllib3, sys, uuid
import ssl
def send_verification_code(request):
if request.method == "POST":
phone_number = request.POST.get('phone_number')
try:
user = User.objects.get(phone_number=phone_number)
coding = phonetest(phone_number)
user.verification_code = coding
user.acquiretime = datetime.datetime.now()
user.save()
# 生成一个随机验证码并存入数据库(这里简单示例,实际可优化生成逻辑)
return HttpResponse("验证码已发送")
except User.DoesNotExist:
return HttpResponse("该手机号未注册")
return render(request,'send_code.html')
def verify_login(request):
if request.method == "POST":
phone_number = request.POST.get('phone_number')
entered_code = request.POST.get('verification_code')
try:
user = User.objects.get(phone_number=phone_number)
nowtime = datetime.datetime.now().replace(tzinfo=datetime.timezone.utc)
if (nowtime - user.acquiretime).seconds > 300:
return HttpResponse("验证码已过期")
if user.verification_code == entered_code:
user.is_verified = True
user.save()
return HttpResponse("登录成功")
return HttpResponse("验证码错误")
except User.DoesNotExist:
return HttpResponse("该手机号未注册")
return render(request,'verify_login.html')
def phonetest(phone):
host = 'https://zwp.market.alicloudapi.com'
path = '/sms/sendv2'
method = 'GET'
appcode = '你的appcode'
coding = str(random.randint(100000, 999999))
msg = '【智能云】您的验证码是' + coding + '。如非本人操作,请忽略本短信'
# msg = '【智能云】您的验证码是568126。如非本人操作,请忽略本短信'
utfmsg = msg.encode('utf-8')
# phone = '你的手机号'
querys = 'mobile=' + phone + '&content=' + urllib.parse.quote(msg)
# querys = 'mobile=15890137517&content=' + urllib.parse.quote(utfcoding)
# querys = 'mobile=17629869989&content=%E3%80%90%E6%99%BA%E8%83%BD%E6%95%99%E8%82%B2%E3%80%91%E6%82%A8%E7%9A%84%E5%AF%86%E7%A0%81%E6%89%BE%E5%9B%9E%E9%AA%8C%E8%AF%81%E7%A0%81%E6%98%AF%35%31%34%31%31%34%E3%80%82'
bodys = {}
url = host + path + '?' + querys
http = urllib3.PoolManager()
headers = {
'Authorization': 'APPCODE ' + appcode
}
response = http.request('GET', url, headers=headers)
content = response.data.decode('utf-8')
return coding
上面是两个视图函数,一个是接收手机号,另一个是进行验证。(没有js就只能这样了,接收验证码和输入验证码放两个html)
这里需要你改的只有appcode和mobile两个;
其次是models.py代码:
from django.db import models
class User(models.Model):
phone_number = models.CharField(max_length=11, unique=True) # 手机号
is_verified = models.BooleanField(default=False) # 是否已验证
verification_code = models.CharField(max_length=6, blank=True, null=True) # 验证码
acquiretime = models.DateTimeField(max_length=50, null=True) # 验证码获取时间
这里别忘了makemigrations和migrate迁移数据一下。
接下来是发送验证码和输入验证码的两个html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>发送验证码</title>
</head>
<body>
<form method="post" action="">
{% csrf_token %}
<label for="phone_number">手机号:</label>
<input type="text" id="phone_number" name="phone_number" required><br>
<input type="submit" value="发送验证码">
</form>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>验证登录</title>
</head>
<body>
<form method="post" action="">
{% csrf_token %}
<label for="phone_number">手机号:</label>
<input type="text" id="phone_number" name="phone_number" required><br>
<label for="verification_code">验证码:</label>
<input type="text" id="verification_code" name="verification_code" required><br>
<input type="submit" value="验证登录">
</form>
</body>
</html>
我感觉没什么好指出的。

以上是效果。
接下来就是urls.py了:
urls.py分为总url和app里面的url,
首先是总的urls里面的
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('phone.urls')),
]
这里我们创建的app名字位phone:
from django.urls import path
from. import views
urlpatterns = [
path('', views.send_verification_code, name='send_verification_code'),
path('verify_login/', views.verify_login, name='verify_login'),
]
之后我们访问:
http://127.0.0.1:8000/
就可以输入手机号进行验证了

之后访问:
http://127.0.0.1:8000/verify_login/
就可以输入验证码进行验证了:

我们在输入发送验证码的那一刻,我们就可以在mysql中查看我们的验证码。
这也是后端可以验证的方法。

至此,发送手机验证码就是这样了。
此外还有一个小坑,就是关于两个时间的计算:
避坑手册!Python 对比两个 datetime 大小的坑 - python后端实战经验分享 - SegmentFault 思否
更多推荐
所有评论(0)