注册的逻辑
-
注册需要的参数用户名,密码等,主要是图片验证码等输入
-
输入图片验证码之后,点击获得验证码,这时候要验证图片验证码的正确性
-
图片验证码正确才会发生短信,用户收到短信之后,输入后,点击注册就可以把数据写入数据库。
图片验证码的作用是防止短信发送的浪费,但是背后真的那么简单吗?想多了,下面讲一下细节。这是代码===>
class RegisterForm(forms.Form):
username = forms.CharField(label='用户名', max_length=20, min_length=5,
error_messages={"min_length": "用户名长度要大于5",
"max_length": "用户名长度要小于20",
"required": "用户名不能为空"}
password = forms.CharField(label='密码', max_length=20, min_length=6,
error_messages={"min_length": "密码长度要大于6",
"max_length": "密码长度要小于20",
"required": "密码不能为空"}
password_repeat = forms.CharField(label='确认密码', max_length=20, min_length=6,
error_messages={"min_length": "密码长度要大于6",
"max_length": "密码长度要小于20",
"required": "密码不能为空"}
mobile = forms.CharField(label='手机号', max_length=11, min_length=11,
error_messages={"min_length": "手机号长度有误",
"max_length": "手机号长度有误",
"required": "手机号不能为空"})
sms_code = forms.CharField(label='短信验证码', max_length=6, min_length=6,
error_messages={"min_length": "短信验证码长度有误",
"max_length": "短信验证码长度有误",
"required": "短信验证码不能为空"})
def clean_username(self):
check mobile
:return:
uname = self.cleaned_data.get('username')
if Users.objects.filter(username=uname).exists():
raise forms.ValidationError("用户名已注册,请重新输入!")
return uname
def clean_mobile(self):
tel = self.cleaned_data.get('mobile')
if not re.match(r"^1[3-9]\d{9}$", tel):
raise forms.ValidationError("手机号码格式不正确")
if Users.objects.filter(mobile=tel).exists():
raise forms.ValidationError("手机号已注册,请重新输入!")
return tel
def clean(self):
cleaned_data = super().clean()
passwd = cleaned_data.get('password')
passwd_repeat = cleaned_data.get('password_repeat')
if passwd != passwd_repeat:
raise forms.ValidationError("两次密码不一致")
tel = cleaned_data.get('mobile')
sms_text = cleaned_data.get('sms_code')
redis_conn = get_redis_connection(alias='verify_codes')
sms_fmt = "sms_{}".format(tel).encode('utf8')
real_sms = redis_conn.get(sms_fmt)
if (not real_sms) or (sms_text != real_sms.decode('utf8')):
raise forms.ValidationError("短信验证码错误")
首先图片验证码已开始加载的时候放在哪里?当用户点入注册页面,会自动生成图片验证码,并且保存在redis中,为了保证图片key和其他用户的不一致,前端会传一个参数uuid,这样redis里面就保存了一个这样的键指对了。
img_aksjdknwas(uuid): 9821(图片验证码)
class ImageCode(View):
def get(self, request, image_code_id):
text, image = captcha.generate_captcha()
conn_redis = get_redis_connection('verify_codes')
img_key = "img_{}".format(image_code_id).encode('utf8')
conn_redis.setex(img_key, constants.IMAGE_CODE_REDIS_EXPIRES, text)
logger.info("Image code:{}".format(text))
return HttpResponse(content=image, content_type='image/jpg')
那什么时候拿出来呢?当然是点击注册的时候要验证,就要拿出来。
form = forms.CheckImgCodeForm(data=dict_data)
下面是验证图片验证码的正确性,要去redis里面查出来,同时生成一个手机号60s内不能再次发生的标志保存进redis数据库。
class CheckImgCodeForm(forms.Form):
check image code
mobile = forms.CharField(max_length=11, min_length=11, validators=[mobile_validator, ],
error_messages={"min_length": "手机号不能为空"
,
"max_length": "手机号不能为空",
"required": "手机号不能为空",
image_code_id = forms.UUIDField(error_messages={"required": "图片UUID不能为空"})
text = forms.CharField(max_length=4, min_length=4,
error_messages={"min_length": "图片验证码长度有误",
"max_length": "图片验证码长度有误",
"required": "图片验证码不能为空",
def clean(self):
cleaned_data = super().clean()
image_text = cleaned_data.get('text')
mobile_num = cleaned_data.get('mobile')
image_uuid = cleaned_data.get('image_code_id')
if Users.objects.filter(mobile=mobile_num).count():
raise forms.ValidationError("手机号已经注册,请重新输入!")
try:
con_redis = get_redis_connection(alias='verify_codes')
except Exception as e:
raise forms.ValidationError("未知错误")
img_key = "img_{}".format(image_uuid).encode('utf8')
real_image_code_origin = con_redis.get(img_key)
real_image_code = real_image_code_origin.decode('utf-8') if real_image_code_origin else None
con_redis.delete(img_key)
if (not real_image_code) or image_text.upper() != real_image_code:
raise forms.ValidationError("图片验证失败")
sms_flag_fmt = "sms_flag_{}".format(mobile_num).encode('utf8')
sms_flag = con_redis.get(sms_flag_fmt)
if sms_flag:
raise forms.ValidationError("获取手机短信验证码过于频繁")
class CheckUsernameView(View):
GET username/(?<username>\w{5,20})/
def get(self, request, username):
count = Users.objects.filter(username=username).count()
data = {
'username': username,
'count': count,
return to_json_data(data=data)
class CheckMobileView(View):
GET mobiles/(?P<mobile>1[3-9]\d{9})/
def get(self, request, mobile):
data = {
'mobile': mobile,
'count': Users.objects.filter(mobile=mobile).count()
return to_json_data(data=data)
上面的代码是检查数据库中是否有一样的手机号和用户名。
下面可以发送短信验证码了吧,烦死了!!!🤗🤗
生产短信验证码,保存在redis数据库里,这里保存的话用到了redis的pipeline技术和redis进行交互。然后通知平台进行发送(这里用了celery技术)。
class SmsCodesView(View):
1,获取参数
2,验证参数
3,发送信息
4,保存短信验证码
5,返回给前端
POST /sms_codes/
-检查图片验证码是否正确
-检查是否60秒有记录
-生成短信验证码
-发送短信
def post(self, request):
json_data = request.body
if not json_data:
return to_json_data(errno=Code.PARAMERR, errmsg=error_map[Code.PARAMERR])
dict_data = json.loads(json_data.decode('utf8'))
form = forms.CheckImgCodeForm(data=dict_data)
if form.is_valid():
mobile = form.cleaned_data.get('mobile')
sms_num = "%06d" % random.randint(0, 999999)
con_redis = get_redis_connection(alias='verify_codes')
sms_flag_fmt = "sms_flag_{}".format(mobile).encode('utf8')
sms_text_fmt = "sms_{}".format(mobile).encode('utf8')
pl = con_redis.pipeline()
try:
pl.setex(sms_flag_fmt, constants.SEND_SMS_CODE_INTERVAL, 1)
pl.setex(sms_text_fmt, constants.IMAGE_CODE_REDIS_EXPIRES, sms_num)
pl.execute()
except Exception as e:
logger.debug('redis 执行异常{}'.format(e))
return to_json_data(errno=Code.UNKOWNERR, errmsg=error_map[Code.UNKOWNERR])
logger.info('SMS code:{}'.format(sms_num))
expires = constants.SMS_CODE_REDIS_EXPIRES
sms_tasks.send_sms_code.delay(mobile, sms_num, expires, constants.SMS_CODE_TEMP_ID)
return to_json_data(errno=Code.OK, errmsg="短信验证码发送成功")
else:
err_msg_list = []
for item in form.errors.get_json_data().values():
err_msg_list.append(item[0].get('message'))
err_msg_str = '/'.join(err_msg_list)
return to_json_data(errno=Code.PARAMERR, errmsg=err_msg_str)
用户收到短信验证码后填入就大概注册完成了。
https://blog.csdn.net/weixin_43673156/article/details/123981998
celery异步任务
sms_tasks.send_sms_code.delay(mobile, sms_num, expires, constants.SMS_CODE_TEMP_ID)
Celery 是一个 基于python开发的分布式异步消息任务队列,通过它可以轻松的实现任务的异步处理, 如果你的业务场景中需要用到异步任务,就可以考虑使用celery.
1.你想对100台机器执行一条批量命令,可能会花很长时间 ,但你不想让你的程序等着结果返回,而是给你返回 一个任务ID,你过一段时间只需要拿着这个任务id就可以拿到任务执行结果, 在任务执行ing进行时,你可以继续做其它的事情。
2.你想做一个定时任务,比如每天检测一下你们所有客户的资料,如果发现今天 是客户的生日,就给他发个短信祝福
Celery 在执行任务时需要通过一个消息中间件来接收和发送任务消息,以及存储任务结果, 一般使用rabbitMQ or Redis 或者是数据库来存放消息的中间结果
简单:一旦熟悉了celery的工作流程后,配置和使用还是比较简单的
高可用:当任务执行失败或执行过程中发生连接中断,celery 会自动尝试重新执行任务
快速:一个单进程的celery每分钟可处理上百万个任务
灵活: 几乎celery的各个组件都可以被扩展及自定制


一、流程分析:
1.用户在项目前端,输入手机号,然后点击【获取验证码】,将手机号发到post到后台。
2.后台验证手机号是否合法,是否已被占用,如果通过验证,则生成验证码,并通过运行脚本,让短信运营商向该手机号,发送该验证码,如果没通过验证,则返回错误信息
3.用户收到短信验证码以后,再次将所有信息post到后台。
4.后台验证各个数据,通过验证则完成实名制认证,如果没通过则返回错误信息。
总结,一次实名验证,需要两次ajax+post
二、对接短信商:
1.在云片网端:
1.注册云片网
地址:https://www.yunpian.com/
后台管理控制台页面:其中最重要的信息是APIKEY
移动飞信代发服务数据库编程接口说明
移动飞信代发服务接口使用数据库记录查询方式实现,支持MS SQL及Access数据库,只用到一个FetionTb表进行交换,运行之前请先创建好FetionTb表,然后配置SYSSET.INI文件的"数据库类型"及"连接字符串"。
一、FetionTb表结构字段含意如下:
id字段(自动编号):主键,标识不同的命令记录
Com字段(字符型,长20):命令字符串,支持四个命令是"发送短信"、"添加好友"、"好友列表"、"接收短信"
myMNo字段(字符型,长20):发送短信手机的号码
myMPass字段(字符型,长30):发送短信手机的飞信密码
toMNo字段(字符型,长250):接收短信手机的号码,多个接收号码可以用逗号","分开
(是飞信好友才会发送成功,当与发送手机号相同时就会发给自己了)
Msg字段(字符型,长250):短信内容,不能超过移动短信要求的长度
reok字段(数字型):命令记录处理状态,有4个值表示,-1=正在处理中,0=等待处理中,1=处理完成,2=已经提取处理结果,10=收到的短信
retxt字段(备注型):处理完成后返回的信息
addTime字段(时间型):记录加入时间或最后处理时间
mtype字段(字符型,长20):可以是任意字符,客户程序可用来自行定义命令执行区分标志
二、客户程序发送流程:
1)客户程序将命令记录(如"发送短信")插入表(注意reok字段要等于0,retxt字段要为空)
SQL语句例:INSERT FetionTb(Com,myMNo,myMPass,toMNo,Msg,reok,retxt,addTime,mtype)
VALUES('发送短信','13700000008','888888','13600000088','你好!',0,'',getdate(),'1234')
2)客户程序定时查询执行结果,主要查reok字段是否变为1
SQL语句例:SELECT retxt from FetionTb where reok=1 and myMNo='13700000008' and toMNo='13600000088' and mtype='1234'
当结果不为空时说明记录执行完成
3)客户程序查到命令结果后,还要把reok字段改为2,以通知服务程序命令完成,可以删除此记录了
SQL语句例:UPDATE FetionTb SET reok=2 where reok<>0 and myMNo='13700000008' and toMNo='13600000088' and mtype='1234'
注:如果不修改reok字段改为2,服务程序也会在10分钟至1个半小时左右删除已经执行完成的记录,如要保存发送记录,请自行记录到别的表。
对于"添加好友"命令,Msg字段可以为空串;"好友列表"命令toMNo字段与Msg字段可以为空串
三、好友列表返回结果说明:好友之间以逗号","分开,每个好友又以"|"分开名称与手机号码,客户程序可以把字符串处理分割成列表。
例如:"张三|13788888881,李四|1360000002"
四、接收短信说明:“接收短信”是服务程序收到的当前号码短信,reok字段为10,用户以这个为条件查收短信,查收后请把reok字段改为2,或直接删除。
附件: 数据库审计系统需求说明 序号 指标项 具体要求 1 硬件指标 标准机架式设备,不少于 6个1000M电口,不少于 2个SFP光口(带SFP模块), 具备独立的管理口和 HA 口;可用磁盘空间不小于 2T;吞吐能力》2000M峰值处 理能力》18000条/秒,根据任意sql条件查询性能》2000万条/秒;日志存储量 > 6亿条;双冗余电源。 2 工作模式 旁路镜像模式部署,不影响数据库性能和网络架构;支持 IPV6环境部署和IPV6 环境下数据库的审计;支持分布式部署,管理中心可实现统一配置、统一报表、 统一查询。 管理中心和探测器都可存储审计数据,实现大数据环境下磁盘空间的有效利用和 扩展;管理中心和探测器直接的数据传输速率、时间、端口都可自定义。 3 协议支持 支持主流数据库: Oracle、SQLServer、Mysql、DB2 infomix、Sybase、CACH、 达梦、人大金仓、神舟 Oscar、南大通用 GBASE数据仓库teradata。 支持主流业务协议: TeInet、SMTP POP3 DCOM 4 审计内容 审计日志包括账号、 SQL语句、表、字段、存储过程、客户端工具、 IP、MAC实 例名、主机名等条件。 支持双向审计,特别是返回字段和结果、执行状态、返回行数、执行时长等内容, 并能够根据返回结果设置审计策略,要求在不连接被审计数据库情况下完成。 支持HTTP请求审计,提取URL POST/GETf直、cookie、操作系统类型、浏览器 类型、原始客户端IP、MAC地址、提交参数等。 可与堡垒主机进行联动,实现用户信息的定位。 5 智能发现 自动识别流量中存在的数据库,也可通过扫描发现网络中的数据库。 支持定期自动扫描数据库漏洞和不安全配置,提供漏洞扫描报告。 6 运维审计 支持tel net、ftp、SSH协议及其他私有协议的旁路会话审计;会话审计日志应含 源IP、目的IP、会话起始时间、会话结束时间、连接时长、会话总流量等维度。 支持数据库协议解析成会话形式,并支持一键关联到具体的 SQL操作会话。 支持根据目的IP、目的端口、源IP及时间范围对会话进行检索。 7 模型分析 可智能学习数据库的访问行为建立模型。 可通过行为轨迹图方式展示数据库访问行为。 可基于账号、IP地址、访问权限、客户端工具等维度对行为模型做钻取分析、变 更分析,对学习的安全基线以外的行为自动智能的进行告警。 可以自动对比不冋时期的行为模型,以区分其审计日志数趋势、用户、 IP地址、 工具、访问权限的差异情况。 8 规则分析 支持账号、IP地址、MAC地址、操作类型、返回行数、执行时 、表、字段、主 数据库审计系统需求说明全文共2页,当前为第1页。 数据库审计系统需求说明全文共2页,当前为第1页。 机名、操作系统名、关联表数,实现对敏感信息的精细监控。 支持基于返回结果集大小、返回内容、具体报文内容的细粒度审计规则。 内置高危SQL查询和注入、远程命令执行、跨站脚本攻击、 FTP和telnet高危指 令等审计规则不少于 300种。 规则可支持导入、导出、优先级调整、分组、批量加载等。 9 白名单 支持用户名、操作类型、IP地址、客户端工具、系统用户名、主机名、 MAC地址、 SQL语句等条件设置白名单,条件不少于 10个。 10 告警与报表 支持短信、邮件、syslog、snmp ftp等告警方式,支持冋时发送多人、 聚合发送、 单条发送、重发、发生统计等高级告警功能。 可以根据单个库、数据库组生成报表,包括支持严格按照塞班斯( SOX法案、等 级保护标准要求生成多维度综合报告。 支持按照数据库访问行为生成报表,智能识别帐号的增删、权限变更、密码修改、 特权操作等行为。 支持按照时间曲线统计流量、在线用户数、并发会话、 DDL操作数、DML操作数、 执行量取多的SQL语句等报表。 11 日志数据管 理 审计数据保留策略应至少满足天数和百分比两个控制参数,且支持 web界面可配 置,且恢复数据不影响正常的审计功能。 支持自动备份审计日志,备份完后通过 FTP方式外送到外部设备;备份文件需要 进行加密,且必须导入设备才能够进行恢复查看。 12 系统排错 系统内置故障排错系统,可以支持一键排错对服务异常、许可证异常、流量异常 等大部分常见故障的检测,并可提供快速的解决办法。 支持流量分析功能,包括抓包、包内容查看、自动探测 sql语句等。 13 资质要求 具备公安部颁发的《计算机信息系统安全专用产品销售许可证》。 14 售后服务 原厂五年售后服务,包括安装调试、硬件质保、软件升级、特征库升级等。 数据库审计系统需求说明全文共2页,当前为第2页。 数据库审计系统需求说明全文共2页,当前为第2页。 数据库审计系统需求说明
在前端页面添加有关短信验证的标签:
<input type="text" name="msg_code" id="msg_code" v-model="sms_code" @blur="check_sms_code">
<a href="javascript:;" @click="send_sms_code">[[sms_code...
验证用户名: 必须由字母, 数字下划线组成, 并且长度为 5 到 12 位
验证密码: 必须由字母, 数字下划线组成, 并且长度为 5 到 12 位
验证确认密码: 和密码相同
邮箱验证: xxxxx@xxx.com
验证码: 现在只需要验证用户已输入。 因为还没讲到服务器。 验证码生成
首先需要写html编程中的body主体部分,注入图片,输入文本框,以及注册按钮等。
body代码部分
这里选用的短信发送平台:榛子云短信平台:1.在"我的应用"->"详情"中打开:记住appId appSecret2. 下载开发包下载地址:http://smsow.zhenzikj.com/doc/sdk.html记住下载python3版本下面直接上代码#!/usr/bin/env python#coding=utf-8#导入包from captcha import zhenzismscli...
Fdog系列(一):思来想去,不如写一个聊天软件,那就从仿QQ注册页面开始吧。
Fdog系列(二):html写完注册页面之后怎么办,用java写后台响应呀。
文章中出现的源码获取方式:评论区留下邮箱地址。
创作不易,各位看官点个关注,点个赞呗!
1. 前言
前面两篇分别使用html写了前端网页和使用java写后端响应代码,实现了前端与后端的数据交互,今天这篇将介绍如何将数据写入数据库,并且实