Flask项目之手机端租房网站的实战开发(六)

news/2024/5/15 6:29:51/文章来源:https://blog.csdn.net/weixin_30384217/article/details/95149318

说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家!

接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/85858348

目录

一丶补充

二丶短信验证码前端编写 

三丶注册后端接口编写

四丶注册后端测试

五丶注册前端编写

六丶用户注册功能测试


一丶补充

1.之前写的获取的图片验证码,有一个地方需要做进一步的处理,需要删除redis数据库中的图片验证码,防止用户使用同一个图片验证码验证多次,所以将删除代码放在取出redis数据库中图片验证码的值之后,也就是在real_image_code变量之后进行删除,这样即使删除了redis数据中的数据,也不会影响接下来的判断校验,这样做的目的就是说不管用户填对填错,只有一次验证机会

2.测试以上逻辑是否正确

  • step1 重新运行程序,刷新http://127.0.0.1:5000/register.html 注册页面

  • step2 查看redis数据库图片验证码的值

  • step3 在Postman工具中发送短信验证码路由地址

此时绑定的手机号码上就会收到我们定义的6位数验证码

  • step4 查看redis数据库(这个时候并没有超过180秒),发现图片验证码的key已经被删除

3.短信验证码这一块,大多网站都会在用户发送第一次验证码后,在前端页面会出现60s后再试之类的提醒,那么对于后端来说,也是需要的,比如被人知道了后我端口的接口,1分钟之类不断的发送短信,那可就不好了,所以为了做到优化以及安全防范,那么就需要在后端进行一个禁止60s内发送第二次短信的一个逻辑,不仅仅限于前端

  • step1 逻辑分析,首先当发送第一次短信时,需要记住发送短信记录,当时间超过60s以上,才可以发送第二条短信,此时就需要想想是在什么时候将这个发送短信的记录存到redis数据库,大多公司是这样做的,不管发送成功与否,都是需要等待60s后才能发送第二次,所以我们这里也是这样做的,在发送短信之前就将记录存到redis数据库当中去
  • step2 当在保存短信验证码的时候,将这个第一次发送短信的记录存到redis数据库中,让redis数据库去维护记录的有效期60s,这个记录的数据随便起,这里设置1,那么当在redis数据库查询不到这个记录时,代表可以记录过了有效期被删除了,则代表可以发送第二条短信验证码了
redis_store.setex("send_sms_code_%s" % mobile, constants.SEND_SMS_CODE_INTERVAL, 1)
  • step3 然后在判断手机号是否注册之前进行校验判断,判断对于此手机号码在60s以内有没有之前发送短信的操作,如果有,则不代表用户操作频繁,不予处理(注:经测试如果在判断获取记录的值的时候代码为if send_flag == 1时,会出现bug,所以建议使用is not None即可)

4.测试以上逻辑是否正常

  • step1 启动项目程序

  • step2 刷新http://127.0.0.1:5000/register.html 注册页面,生成新的图片验证码,将验证码内容以及对应编码通过发送短信路由发送到对应接口进行测试

  • step3 此时从redis数据库中查看图片验证码的id以及值

  • step4 在Postman工具中,对短信接口地址进行访问,并携带image_code以及image_code_id

同时收到手机短信验证码

  • step5 最关键的一步,与此同时,刷新图片验证码,获取新的图片验证码,然后在redis数据查询id以及图片验证码的值后在Postman中进行再次发送(注:这里的演示是在60s之内发送第二次请求给后端短信接口),出现如下提示,代表逻辑正确

二丶短信验证码前端编写 

1.在register.js中构造请求数据

var req_data = {"image_code": imageCode,  //用户输入图片验证码的值"image_code_id": imageCodeId  //对应图片验证码的编号};

2.通过ajax方式想后端去发送请求

// 想后端发送请求
$.get("/api/v1.0/sms_codes/"+mobile, req_data, function (resp) {// 回调函数中的resp是后端返回的json字符串,通过ajax将这个字符串转换成js对象// 所以这里的resp为ajax转换后的对象if (resp.error == "0") {// 表示发送成功var num = 60;var timer = setInterval(function () {if (num>1) {// 修改倒计时的文本内容$(".phonecode-a").html(num + "s");num -= 1} else {$(".phonecode-a").html("获取验证码");$(".phonecode-a").attr("onclick", "sendSMSCode();");clearInterval(timer)}}, 1000, 60)} else {alert(resp.errmsg);$(".phonecode-a").attr("onclick", "sendSMSCode();");}});

3.测试

  • step1 启动程序

  • step2 访问http://127.0.0.1:5000/register.html 注册界面

  • step3 输入手机号,图片验证码后点击获取短信验证码,成功出现倒计时,同时手机收到短信验证码

手机验证码

  • step4 在谷歌浏览器中查看接口地址的NetWork

General数据

Response响应数据 

三丶注册后端接口编写

1.在项目api_1_0目录下创建passport.py文件用作于注册以及登录的逻辑接口文件

2.构建register视图函数,并在ihome/init文件中导入passport模块

@api.route("/users", methods=["POST"])
def register():pass

3.逻辑编写

  • step1 获取前端请求发送请求中的json数据
req_dict = request.get_json()
mobile = req_dict.get("mobile") #跟前端约定好的
sms_code = req_dict.get("sms_code")
password = req_dict.get("password")
password2 = req_dict.get("password2")
  • step2 校验参数
if not all([mobile, sms_code, password, password2]):return jsonify(errno=RET.PARAMERR, errmsg="请求参数不完整")
  • step3 判断用户输入的手机号码格式

  • step4 从redis数据库中取出短信验证码
try:real_sms_code = redis_store.get("sms_code_%s" % mobile)
except Exception as e:current_app.logger.error(e)return jsonify(errno=RET.DBERR, errmsg="读取真实短信验证码异常")
  • step5 判断短信验证码是否过期
if real_sms_code is None:return jsonify(errno=RET.NODATA, errmsg="短信验证码失效")
  • step6 判断用户输入的短信验证码是否正确
if real_sms_code != sms_code:return jsonify(errno=RET.DATAERR, errmsg="短信验证码填写错误")
  • step7 同图片验证码一样,在redis数据库中进行删除,防止一个短信验证码多次使用
try:redis_store.delete("sms_code_%s" % mobile)
except Exception as e:current_app.logger.error(e)
  • step8 判断用户的手机号是否注册过

  • step9 将用户注册的数据保存到mysql数据库中,这时候为了减少数据库的查询,不增加程序运行的负荷,所以我们在判断用户手机号是否注册过的时候,不再进行查询,而是在保存用户注册数据时候,判断手机号码是否存在,因之前在models中创建数据库表时,将mobile字段的数据设置为唯一约束,所以当数据库ih_user_profile表中已存在mobile字段的数据时,再进行插入相同手机号mobile的数据时,mysql数据库则会抛出异常,那么我们就利用数据库抛出的异常来判断手机号码是否存在,从而减少在视图函数中数据库的查询

数据库测试mobile字段异常

  •  step10 注释step8代码重新编写,大体如下,因密码需要进行加密后再存到数据库,所以到最后面再进行处理

说明:这里的注册名为手机号,后面会另写接口让name为名字昵称,当出现异常时候,需要进行数据库回滚操作

  • step11 将登陆状态保存到session中,并返回注册成功结果
session["name"] = mobile
session["mobile"] = mobile
session["user_id"] = user.idreturn jsonify(errno=RET.OK, errmsg="注册成功")
  • step12 将用户输入的密码进行加密

说明:将对用户输入的密码添加salt值(盐值),再进行加密存储,说白了就是,在户输入的密码基础上再添加一个随机生成的字符串,即使用户1和用户2密码一样,但在进行salt处理后,在数据库中也不会相同,不存在撞库说法,这样做安全性极高,即使密码泄露,破解出来后也并不是用户的真是密码

问题:反过来当用户注册成功后,进行用户登录时,那么这个密码是如何进行判断?是将用户输入的密码进行加密后再和数据库加密密码进行对比,可是当初在注册时对用户输入的密码进行加密时候添加了随机的salt值,所以这里需要注意思考一下,我们这里的想法是通过在注册时候将salt值进行保存在数据库中另起一个字段,这是其一方法,其二是将这个salt值与加密后的密码中间以某个分隔符进行分隔,这样做的话就不用再创建表字段另存salt值,如qwe@ohcuncacaucaooa08c03qoca08q08,@符前为salt值,后为用户加密后的密码

:MD5已被攻破,利用暴力测试以及算法公式成功反推出加密前的密码,sh1估计等不了几年就会被破解,我们这里使用的是sha256进行密码的加密

①在models文件中通过导入werkzeug.security类中的generate_password_hash方法将密码进行加密,并存到数据库中

def generate_password_hash(self, origin_password):self.password_hash = generate_password_hash(origin_password)

②在passport文件中,在构建User对象的时候,通过调用models文件中的generate_password_hash方法,将前端用户输入的password传参给此方法,并保存到User模型类的passwor_hash字段中

user.generate_password_hash(password)

4.property装饰器的使用

  • step1 将函数调用转换为对象属性设置(在passport文件中)
user.password = password
  • step2 在models中注释之前的generate_password_hash方法的调用,使用property装饰器对新创建的password函数装饰为password属性(注,在passport文件中user.password对象的password属性名要与models文件中的方法同名),再通过password属性的setter方法,设置类属性的值,这个值就是我们在passport文件中通过user.password = password这个password值

四丶注册后端测试

  • step1 因测试users注册后端接口使用的POST请求方式,而此时还没有编写注册前端端口测试,所以需要在ihome/init文件中将csrf后端机制关闭,再进行测试
# 为flask补充csrf防护
# CSRFProtect(app)
  • step2 运行程序,在浏览器输入http://127.0.0.1:5000/register.html,进入注册页面,

  • step3 在注册页面输入错误手机号,正确的图片验证码,当点击获取短信验证码时候,会提示发送短信失败,无所谓,我们从redis数据库直接读取sms_code即可

  • step4 在redis数据库中获取短信验证码(因为在上一步输入的是错误手机号,导致无法发送短信,测试无所谓嘛)

  • step5 在测试工具Postman中,添加127.0.0.1:5000/api/v1.0/users地址,构造json格式的body体数据,就是我们注册页面所需要的数据,成功返回注册成功响应数据,代表注册后端接口没问题

  • step6 响应数据表示注册成功后,查看数据库ih_user_profile表信息,第一条数据是之前测试使用的

五丶注册前端编写

1.前端注册HTML代码(不展示)

2.前端注册JS代码(不展示)

3.在register.js文件中通过ajax方式向后端接口发送注册请求(在callback for submit())

// 调用ajax向后端发送注册请求var req_data = {mobile:mobile,sms_code:phoneCode,password:passwd,password2:passwd2};var req_json = JSON.stringify(req_data)$.ajax({url:"/api/v1.0/users",type:"post",data:req_json,contentType:"application/json",dataType: "json",headers:{"X-CSRFToken":getCookie("csrf_token")},success: function (resp) {if (resp.errno== "0"){// 注册成功,即跳转到主页location.href = "/index.html";}else {alert(resp.errmsg);}}})

4.在js构建一个getCookie的方法来获取前端名为csrf_token的cookie的值

function getCookie(name) {var r = document.cookie.match("\\b" + name + "=([^;]*)\\b");return r ? r[1] : undefined;
}

 5.将获取的cookie的值,放在请求头中的X-CSRFToken键中,方便后端进行csrf验证(需将ihome/init中的CSRF验证开启)

headers:{"X-CSRFToken":getCookie("csrf_token")},

六丶用户注册功能测试

1.进行注册测试,输入不存在的号码是为了演示给大家,虽然提示发送短信验证码失败,但我可以从redis数据库去拿取短信验证码,注册成功后,即跳转到登录页面

2.用户注册成功后,查看数据库中ih_user_profile表的内容,成功将用户注册信息保存到数据库

转载于:https://www.cnblogs.com/cdtaogang/p/10631082.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_776536.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ASP.NET Core 2.0 使用支付宝PC网站支付

前言 最近在使用ASP.NET Core来进行开发,刚好有个接入支付宝支付的需求,百度了一下没找到相关的资料,看了官方的SDK以及Demo都还是.NET Framework的,所以就先根据官方SDK的源码,用.NET Standard 2.0 实现了支付宝服务端…

python 爬取图片、没有后缀名_初学Python-只需4步,爬取网站图片(附py文件)

很多人学习Python很重要的一个原因是,可以很简单的把一个网站的数据爬下来。尤其是做我们这一行,产品经理,电商行业。领导:弄一个买卖游戏周边商品的交易APP出来。我:行,那我们卖什么呀?领导&am…

python 实现爬取网站下所有URL

python3 实现爬取网站下所有URL获取首页元素信息:首页的URL链接获取:遍历第一次返回的结果:递归循环遍历:全部代码如下:小结:python3.6 requests && bs4 采用递归方法,最终爬取网站所有…

企业网站托管外包公司有哪几种形式?

所有的企业网络营销都离不开网站,网站是基础也是核心。试问一句如果企业没有网站维护人员,那么企业选择网站托管公司网站托管公司又包括哪些内容呢?1网站策划任何一个企业的网络营销工作都是从网站策划开始的,前期网站策划的好坏直接影响着后…

自动化测试 (一) 12306火车票网站自动登录工具

还记得2011年春运,12306火车票预订网站经常崩溃无法登录吗。 今天我们就开发一个12306网站自动登录软件。 帮助您轻松订票 通过前两篇博客Fiddler教程和HTTP协议详解,我们了解了Web的原理. Web的原理就是,浏览器发送一个Request给Web服务器…

如何做一个大数据seo人员

作为流量运营者或者SEO人员,对于所从事行业领域的认识往往建立在一种直觉之上,我们很难对一个行业有一个全面的了解,这个行业领域有多宽,流量聚焦在哪里,那些是用户最关心的问题? 有的时候很难准确的把握&a…

7年测试工程师经验,浅谈一下如何测试一个web网站?

最近有工作了一年多的朋友在问我,一个web页面到底怎么测试?我的第一感觉是震惊,天天做web测试,咋还不知道怎么测试呢?再仔细一想,可能是我们每天忙于测试而忽略测试导致的,毕竟当局者迷&#xf…

dz论坛Discuz_X3.4最新网站漏洞

近期我们sinesafe安全部门审计discuz最新版的时候发现配置文件写入导致代码执行的问题。cms安装的时候一般会分为几个步骤去进行,其中有对配置文件config进行写入的步骤,当写入的时候未严格限制传入的参数就存在代码执行问题。 源码信息:Disc…

软件测试:测试一个网站

一、软件测试的原则 1、软件测试应尽早执行,并贯穿于整个软件生命周期 2、软件测试应追溯需求 3、测试应由第三方来构造 4、穷举测试是不可能的,要遵循 Good-enough 原则 5、必须确定预期输出(或结果) 6、必须彻底检查每个测试结果 7、…

网站流量下降的6个原因

网站流量下降的6个原因 有时网络流量会发生变化。有时是最好的。有时候不是那么好。诊断流量变化的原因并不困难。以下是如何控制网络流量以帮助其保持增长。 1.移动范式影响流量 移动正在改变搜索习惯。越来越多的企业注意到搜索模式正在发生变化。这是因为我们正在寻找人们搜…

web网站常用功能测试点总结

一、输入框 1.字符型输入框: (1)字符型输入框:英文全角、英文半角、数字、空或者空格、特殊字符 “~!#¥%……&*?[]{}” 特别要注意单引号和&符号。禁止直接输入特殊字符时&#xff0c…

基于web网站项目的性能测试结果分析

一款对并发要求比较高的web项目,需要对其压力测试,模拟线上可能存在的问题 工具描述: 压力工具:Loadrunner 服务器监控:nmon 数据库:oracle web容器:Tomcat war 项目就好像是一个木桶&…

Linux中什么是动态网站环境及如何部署

当谈论起网站时,我们可能听说过静态和动态这两个词,但却不知道它们的含义,或者从字面意思了解一些却不知道它们的区别。这一切可以追溯到网站和网络应用程序,Web应用程序是一个网站,但很多网站不是Web应用程序&#xf…

微服务 | 微服务网站性能测试

开发者们在工作中经常会遇到过这样的情况:在接手实际项目时,在传统的单体架构下,一个同事负责的功能模块出现故障后,会导致整个系统瘫痪。那么有什么办法才能解决这种问题呢?云上有一种服务——微服务,可以…

九度搜索引擎点击优化_快排会影响到seo优化排名吗?

今天,在seo优化中被人们常提起的就是“快排”,它的出现对seo行业整体冲击很大,不过很多的从事seo优化的站长又说,这种优化方式属于作弊手段,一旦网站做了快排,被搜索引擎发现很容易会惩罚网站,导…

cdn对php网站的加速效果,配置七牛自定义域名cdn加速,让你的网站飞起来

之前发过一篇是没有备案的,使用测试域名来缓存静态文件,效果也是杠杠的。如果你还没有备案,先看这篇文章吧,域名没备案使用七牛cdn加速 。步入正题了(为了节约博主发文的时间,尽量少用文字,多以图片展示&am…

怎么建文件夹_用 GitHub Pages 建个人网站的小白级教程

前段时间心血来潮想建一个个人网站,调研了一圈,试用了 Weebly、Wix、Squarespace 等等产品,感觉都没有办法满足我的奇葩需求……最终还是觉得 GitHub Pages 是最好的——自由、免费、流量够用,目前的访问速度也还不错,…

jsp mysql 注入_Jsp+Mysql网站注入并拿root权限的全过程

很多人可能都知道asp,php的编程要防止sql注入漏洞,而并不知道jsp编程同样也需要防备sql注入漏洞.其实,一旦jsp代码有注入漏洞,将直接影响到整个系统的安全。本文就是主要展示一下我的一次JSPMYSQL注入导出webshell的过程。www.***.***.cn是国内某一个著名研究所的网站&#xff…

模板建站和开发网站区别_模板网站与定制网站有什么区别?

如今存在许多网站设计公司,主要包括使用智能建站和成品网站等的模板网站建设公司还有定制网站建设公司两个大类。这两者都具有各自的优势与不足,接下来我们就将要对这两种不同的网站建设形式进行分析。模板建站和定制建站最显著的差异体现在价格上。正如…

网站服务器机房硬件配置,有关web服务器硬件配置的进阶知识

有关web服务器硬件配置的进阶知识今天,小编来聊一聊web服务器硬件配置,其希望大家对服务器各个配件有一些了解,特别是现在很多人选择组装的方式构建服务器,就更应该用稳定和适用去衡量产品,而不要一味降低成本&#xf…