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

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

目录

一丶在项目中添加静态资源文件

二丶关于csrf防护机制

三丶用户注册模块(图片验证码以及短信验证码)

四丶测试后端verify_code接口是否正确


一丶在项目中添加静态资源文件

1.将静态资源文件拷贝到项目static目录下

2.在终端上运行项目python manage.py runserver

3.在浏览器中输入http://127.0.0.1:5000/static/html/index.html 访问前端主页,如下图

4.当在不使用nginx服务器给用户提供静态资源,而是以flask来提供,当用户在浏览器中输入/static/html/index.html就会显得不友好,正常来说访问主页只需要输入ip地址或者是域名加端口号就可以了,那么就需要我们专门写个视图函数来提供有好的链接地址,把地址前缀给去掉

5.创建一个蓝图,专门负责提供静态文件的

  • step1 在ihome目录下创建一个web_html.py文件
  • step2 创建蓝图html
html = Blueprint("web_html", __name__)
  • step3 在utils目录下创建一个__init__.py文件,使这个目录变成python的包,然后在这个utils包中创建commons.py文件,作为通用工具,在里面定义一个正则转换器

  • step4 在ihome/init文件中,在创建app对象时候,将ReConverter对象添加到app中

  • step5 回到commons.py文件中,定义视图函数get_html

  • step6 在ihome/init中进入此蓝图注册

  • step7 启动项目
python manage.py runserver
  • step8 清除网页缓存数据

二丶关于csrf防护机制

1.csrf验证机制:从cookie中获取一个csrf_token的值,再从请求体中获取一个csrf_token的值,如果这两个值相同,则检
验通过,可以进入视图函数中执行,如果两个值不同,则检验失败,会想前端返回状态码404的错,之前在ihome/init中设置的csrf只是负责验证,并不负责cookie与请求体中的csrf_token的值从哪里来

    # 为flask补充csrf防护
    CSRFProtect(app)

2.分析:前后端不分离时跟django一样直接在模板中进行设置csrf,而我们这个项目使用的是前后端分离,没有模板,对于cookie我们可以提前进行设置csrf_token,然后对于请求体中的cookie而言,当 发送POST请求时,就将那时候的请求体数据中设置csrf_token这样就能csrf防护了

3.设置cookie中的csrf_token

  • step1 为web_html.py中导入csrf包
from flask_wtf import csrf
  • step2 创建一个csrf_token的值
csrf_token = csrf.generate_csrf()
  • step3 导入make_response,将返回的静态文件方法的值构建成响应对象
resp = make_response(current_app.send_static_file(html_file_name))
  • step4 设置cookie的值,有效期为临时会话
resp.set_cookie("csrf_token", csrf_token)
  • step5 重新启动程序,刷新网页,查看我们设置的cookie

三丶用户注册模块(图片验证码以及短信验证码)

1.图片验证码使用流程

  • step1 分析流程:

第一步,需要前端像后端发起一个获取图片验证码的请求,对于后端来说就需要去生成一个随机的验证码图片;第二步将生成的验证码图片返回给前端;第三步验证图片验证码的准确性,如果正确,才能发起获取短信验证码的请求

  • step2 具体细节

在发起获取短信验证码请求的时候将携带填写的图片验证码与后端生成的图片验证码进行校验,因此后端在生成图片验证码的时候,需要将图片进行保存,意义是为了与用户输入的图片验证码进行对比,对比成功,才会给用户返回短信验证码

  • step3 问题分析

后端生成的图片验证码是存在哪里,谁来维护有效期,不可能一张图片一直用下去,所以将在后端生成的图片验证码,存到redis数据库中,在后端进行验证的时候,就从redis中取出这个值,与前端用户输入的值进行对比即可;但是对于多个用户来说同一时间向我发送获取图片验证码时,该怎么去判断谁是谁的,所以要将图片验证码进行编号处理,来分辨是属于哪个用户的图片验证码,那么就需要在用户发起短信验证码请求的携带参数里面除了填写的图片验证码,还需要携带一个用户编号,因此对于后端服务器来说,除了生成图片验证码的值,还需要生成一个对应验证码的编码,一起保存到redis数据库中,还需要将验证码值和编码返回给前端用户,那么就需要从返回的响应体中取解析编码,这样做太麻烦了,为了减轻后端的压力,将不再由后端去生成这个编码了,而是由前端在一开始就去生成这个编号,再前端向后端服务器发起获取图片验证码请求的时候携带一个编码参数,然后后端将编码和图片验证码的值一起存到redis数据库中

  • step4 在ihome/api_1_0目录下创建一个verify_code.py文件,将图片验证码以及短信验证码放在这个文件里面进行使用
  • step5 使用restful风格构建前端向后端发起图片验证码请求地址
GET http://127.0.0.1:5000/api/v1.0/image_codes/<image_code_id>

2.图片验证码后端接口编写

  • step1 将图片验证码工具包captcha拷贝到ihome/utils目录下
  • step2 在verify.py中导入captcha包中的captcha模块中的captcha对象
from ihome.utils.captcha.captcha import captcha
  • step3 通过调用captcha对象中的generate_captcha方法来获取生成的验证码名字,文本内容,以及图片二进制数据
name, text, image_data = captcha.generate_captcha()
  • step4 选择存储数据类型,将验证码的文本内容以及编码存到redis数据库中,并设置有效期

可以使用哈希格式进行存储,但是无法设置单个图片的有效期

示例:

"image_codes": {"id1":"abc", "":""} 哈希  hset("image_codes", "id1", "abc")  hget("image_codes", "id1")

使用字符串格式对数据进行存储,以编码作为key,以文本内容作为value值进行存储即可

示例:

"image_code_编号1": "真实值"
"image_code_编号2": "真实值"
redis_store.set("image_code_%s" % image_code_id, text)
redis_store.expire("image_code_%s" % image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES)
  • step5 在verify.py中导入redis数据库连接对象,然后将编码和文本内容存到redis数据库
from ihome import redis_store

redis_store.set("image_code_%s" %image_code_id, text)
  • step6 设置图片验证码有效期为三分钟,首先在ihome目录下创建一个constants.py文件,用于存放常量
redis_store.expire("image_code_%s" %image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES)

设置值和有效期一步到位

redis_store.setex("image_code_%s" %image_code_id, constants.IMAGE_CODE_REDIS_EXPIRES, text)
  • step7 对于数据库连接,可能会出现连接错误以及连接不上等问题,所以需要捕获异常,并且将捕获到的异常保存到日志中
current_app.logger.error(e)
  • step8 当出现异常后,需要返回错误信息的json数据,先将工程项目定义好的response_code.py响应状态码文件,拷贝到utils中

return jsonify(errno=RET.DBERR, errmsg="save image code failed")
  • step9 没有出现异常,则先通过make_response构造图片image_data数据响应体对象,再设置该响应体对象的请求头中的Content-Type为图片格式jpg,返回给前端

 3.开发流程与编写接口文档

  • step1 开发流程

1. 分析需求
           2. 编写代码
           3. 编写单元测试
           4. 自测
           5. 编写接口文档
           6. 提测代码

  • step2 编写接口文档
接口文档

1. 接口名字
2. 描述(描述清楚接口的功能)
3. url
4. 请求方式
5. 传入参数
6. 返回值

接口:获取图片验证码

描述:前端访问,可以获取到验证码图片

url: /api/v1.0/image_codes/<image_code_id>

请求方式: GET

传入参数:
    格式:路径参数 (参数是查询字符串、请求体的表单、json、xml)

    名字             类型       是否必须      说明
   image_code_id    字符串       是         验证码图片的编号

返回值:
    格式: 正常:图片, 异常:json

    名字             类型       是否必传      说明
    errno          字符串         否        错误代码
    errmsg         字符串         否        错误内容

    实例:
    '{"errno": "4001", "errmsg": "保存图片验证码失败"}'

四丶测试后端verify_code接口是否正确

1.需要在api_1_0/init中导入我们写的接口文件verify_code让蓝图知道有一个verify_code的模块

from . import verify_code

2.运行程序

python manage.py runserver

3.在浏览器中输入http://127.0.0.1:5000/api/v1.0/image_codes/123,成功显示出验证码图片

4.查看程序运行日志

5.此时查看redis数据库中,会发现出现了一个image_code_123的键,获取该键的值就是图片验证码的文本值,说明我们写的后端接口没问题

Flask项目之手机端租房网站的实战开发(四)的更多相关文章

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

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

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

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 一丶项目介绍 产品:关于手机移动端的租房网站 角色:在这个产品中用户包括房东与房客 功能:房东可以在这个平台发布自己的房屋,房客可 ...

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

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

  4. Flask项目之手机端租房网站的实战开发(十四)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

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

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

  6. Flask项目之手机端租房网站的实战开发(十一)

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

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

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

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

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

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

    说明:该篇博客是博主一字一码编写的,实属不易,请尊重原创,谢谢大家! 接着上一篇博客继续往下写 :https://blog.csdn.net/qq_41782425/article/details/8 ...

随机推荐

  1. 手动删除oracle数据库

    --===================== -- 手动删除oracle数据库 --===================== 杀掉进程用此方法比较好,能保证杀得干净,而不是用sql 里面的语句ki ...

  2. df---显示磁盘分区使用空间

    df命令用于显示磁盘分区上的可使用的磁盘空间.默认显示单位为KB.可以利用该命令来获取硬盘被占用了多少空间,目前还剩下多少空间等信息. 语法 df(选项)(参数) 选项 -a或--all:包含全部的文 ...

  3. CSDN博客给我带来的一些诱惑和选择机会(二):HR“邀请于我”,猎头“有求于我”

    上次,2013年10月8日 ,分享了一篇颇具"正能量"的文章CSDN博客给我带来的一些诱惑和选择机会,获得了很好的正面效果. 10月份,又发生了很多有趣.有意义的事情. 其中,有一 ...

  4. cogs 1446. [Commando War,Uva 11729]突击战

    1446. [Commando War,Uva 11729]突击战 ★   输入文件:commando.in   输出文件:commando.out   简单对比时间限制:1 s   内存限制:64 ...

  5. [ES2017] Iterate over properties of an object with ES2017 Object.entries()

    The Object.entries() function is an addition to the ECMAscript scpec in Es2017. This allows us to it ...

  6. SQL 增删改查(具体)

    一.增:有3种方法 1.使用insert插入单行数据: insert [into] <表名> [列名] values <列值> insert into Strdents (na ...

  7. xml中控件调用构造方法

    系统控件view有三个构造方法,分别如下 public DrawView(Context context) { super(context); } public DrawView(Context co ...

  8. Array与ArrayList

    代码图理解复杂代码 类图 1.抽象动物类Animal using System; using System.Collections.Generic; using System.Linq; using ...

  9. Material Design控件使用学习 toolbar+drawerlayout+ Snackbar

    效果 1.,导包design包和appcompat-v7 ,设置Theme主题Style为NoActionbar 2.custom_toolbar.xml <?xml version=" ...

  10. vue --- watch 高级用法

    假设有如下代码: <div> <p>FullName: {{fullName}}</p> <p>FirstName: <input type=&q ...