对于Flask的个人理解及安全相关

这是一个应付技术分享会的文稿 写在开头: 技术分享会写的稿子,文字写的很认真。PPT就。。。应付吧,计划用reveal-md生成PPT (反正第一天感觉好多都好水) 据我认真观察,讲水的大家听段子,讲认真的也没有几个人听,PPT做的炫酷也不过是换来几个抬头几下。更何况屏幕离远点字体就不清晰了,效果比较差。而且干货用PPT讲也很难讲出深度,只能用于科普。所以还不如干脆在blog里分享自己的稿件,梳理一遍自己对于Flask的理解和知识点。

顺便安利一款叫做marp的工具,能够用markdown写PPT。觉得还是很不错的。npm安装后用npx导出为pptx格式一直卡死,最后我直接用vscode插件商店的marp插件就很快导出来了pptx格式

技术分享PPT提纲

[TOC]

Flask基本的概念

  1. 路由

  2. 模板渲染及jinja2引擎

  3. 视图及表单

  4. 数据库及数据库迁移

Flask是什么?

Flask是一种web框架,Flask本身相当于一个内核,其他几乎所有的功能都要用到扩展,都需要用第三方的扩展来实现。用 extension 增加其他功能。Flask没有默认使用的数据库、窗体验证工具。你可以选择MySQL,也可以用NoSQL。其 WSGI 工具箱采用 Werkzeug(路由模块),模板引擎则使用 Jinja2

简而言之,用Flask能够帮助你快速构建一个网站。(比喻的话,就是Flask提供了构建房子的基本骨架,而具体内容的建造则交给用户自己)

(在这一节 Flask的基本概念里 我将用较比较易懂的解释,让大家对flask这个web框架有个很基础的概念 如果有人感兴趣的话,可以尝试一下用flask实现一些个人小项目 )

路由

在Flask框架中,路由 就表示为用户请求的URL找出其对应的处理函数之意。

解释

前端页面的显示是依赖于后台提供的数据的,例如一个博客网站,首页显示的文章,用户来自于数据库。那么路由的作用就是将后台的函数与网页对应的url的绑定起来

模板渲染及jinja2

接下来我们思考这样一个场景,在flask中是如何实现前后端分离的呢?

这里就要提出了flask的模板渲染,和jinja2引擎的概念

之前讲到了url是负责将函数与url绑定,那么模板渲染则可以理解为函数与templates绑定。及具体到渲染哪一个html页面

至于jinja2则是Flask的默认的模板渲染引擎,它的语法,例如一些变量的使用很像vue,前端人员可以直接写templates对应的html/css,而无需在意后端的实现

模板的继承

当然对于一个网站而言,很多页面结构可能出现相似的情况

例如:对于用户的信息显示保持不变,内容发生了改变。如果是这样的话需要写很多内容相似的模板么?在flask这里可以使用模板继承的相关功能

视图函数

其实视图函数的概念在前文已经说出,之前在讲到一个函数会负责与url及html前端关联,这个函数就是视图函数

表单

表单包括什么呢?举个例子,例如用户注册就是一个最简单的表单,如果不考虑使用现成的md轮子,由多个组件组成的发表文章的功能也算是一个表单。

Flask有一套属于自己的表单类(FlaskForm),如果使用的话只需要直接继承该类,并实现对应的字段,例如,实现表单中用户名的定义,只需要在类内实现一个StringField并赋值给一个变量,例如该变量叫username

在视图函数中检查表单内容是否满足要求,则直接看该变量下data的字段是否合乎要求

数据库及数据库迁移

在开头讲到,Flask 没有关联的默认数据库。但是这里一些小型的项目我这里推荐Flask自带的ORM模型,例如Flask-SQLalchemy

它的优点之一简单,它是简化了SQL的具体语法,便捷地创造对应的数据模型

优点之二则是ORM支持多种数据库有很强的可移植性

创建一个模型只需要创建一个类,例如创建一个用户类,代表一个用户所涉及到的全部数据存储项,例如 用户名,id,邮箱,关于甚至可以用ORM模型快速地创建例如一对多的关系

至于数据库迁移,有很多应用场景。这里我来举一个我日常使用的例子,例如在我开发迭代自己个人项目的过程中,突然发现用户的数据对象需要新增一个头像的功能,但是又不希望把以往的数据丢弃,那么可以用数据迁移实现

Flask安全

Flask自身安全:

得益于jinja2引擎,jinja自带XSS过滤,之前我自己在自己项目对表单进行一些自带对特殊字符的过滤,例如< >等,都会发现jinja会自动转义。但是jinja无法避免全部的XSS攻击,例如设置value时变量没有用引号包围

还有就是jinja引擎对标签a的href属性容易存在注入,例如

javascript:alert('unsafe');

最后自身安全讲一下CSRF,这个是可以在Flask的配置中配置的

开发安全

以Flask-admin模块为例,有装饰器login_required来限制仅登录用户可以访问页面,

初次之外flask-admin还能提供记住模式,保存session,退出当前用户等

但是在使用login_required装饰器来限制仅注册用户访问的代码段时,如果考虑不周也会有对应的安全问题

例如:

http://127.0.0.1:5000/login?next=%2Fpost

在应用中,我们用视图函数实现了一个这样的url,当我们登陆后则会重定向到next所指向的位置

这里有一个很严重的安全问题,当我们用request.args.get('next')获取重定向的位置时,很有可能有人恶意在next后使用绝对路径从而绕过一些验证,越权访问到不该访问的页面。所以这里的开发要添加一个检查是绝对路径还是相对路径的函数

以Flask开发为例的web框架的开发,还有类似的场景就是文件上传,例如对文件名的检查,可以使用过长的文件名溢出,或者用特殊字符构造文件名绕过检测

使用异步及Flask自身局限性

异步

  1. 选择broker(消息队列),例如redis

  2. 尝试用celery实现,在__init__中实例化celery以及定义对应的celery配置文件。

  3. 在routes或者其他文件中用celery的装饰器定义对应的异步后台任务

  4. 调用delayapply_async方法执行对应的celery任务

使用缺点:

  • celery4 不支持windows,celery3不支持py3.6及以上
  • celery过重,broker需要redis类型的支持
  • 虽然轻便但是对于一些大型项目的开发比Django不那么完美,尤其是像后台管理系统没有比Django更成熟的能够拿来即用的轮子
  • 和jinja2绑死,无法使用其他模板引擎,例如mako
一篇针对工作后的反思(或许)的碎碎念
使用celery让任务在后台运行(失败,celery不支持windows)
Valaxy v0.18.6 驱动 | 主题 - Yun v0.18.6