本文最后更新于:星期二, 六月 16日 2020, 2:36 下午

要学一学Python的后端框架了,只会php不是个事

0x00 前言

前几天打广东省qwb线下赛的时候,运维的web2就是一个Flask框架的博客,结果我对这个web框架一点了解都没有,语法看不懂,路由也看不懂,结果直接导致这道题白给,被删了站都不想恢复。(后来队友@kk跟我说,这题你只要进了后台就有一个flag怼到你脸上…)感觉这不是个事,还是得把各种主力框架的后台都熟悉一下,要不作为一个web手也太不合格了

0x01 安装Flask

Flask可以说是一个轻型的web框架,相比于传统的apache+php,ngnix+php这些框架,Flask使用python作为主语言,虽然现在并不属于主流,但是相对来说用flask作为框架的网站也慢慢多了起来。

先根据官方文档,在本地搭建一个虚拟环境作为测试的环境,官方对python的版本要求如下:

Python 版本

我们推荐使用最新版本的 Python 3 。 Flask 支持 Python 3.4 及更高版本的 Python 3 、 Python 2.7 和 PyPy 。

在本地新建了一个文件夹执行以下命令(我的测试环境是本地的 Ubuntu WSL,python版本是3.5)

mkdir myproject
cd myporject
python3 -m venv venv

显示我缺少 python3-venv,apt装一下(建议使用清华的apt源)

创建完成之后,目录下会出现一个venv文件夹

激活相应的虚拟环境

. venv/bin/activate

激活之后终端上会显示虚拟环境的名称

然后就可以开始安装Flask了

pip install Flask

0x02 上手

接下来分析一个简单的app

# hello.py
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello_world():
    return 'Hello, World!'
  • 首先app = Flask(__name__)是必须的,这样Flask才能找到模板和静态文件
  • @app.route('/')则告诉了Flask应用如何进行路由处理,即告诉Flask触发函数的URL
  • 函数名称被用于生成相关联的URL,返回值则是显示在页面上的信息

运行应用之前,要先导入环境变量:

export FLASK_APP=hello.py
flask run

界面运行效果如下:

外部可见的服务器

运行服务器后,会发现只有你自己的电脑可以使用服务,而网络中的其他电脑却 不行。缺省设置就是这样的,因为在调试模式下该应用的用户可以执行你电脑中 的任意 Python 代码。

如果你关闭了调试器或信任你网络中的用户,那么可以让服务器被公开访问。 只要在命令行上简单的加上 --host=0.0.0.0 即可:

$ flask run --host=0.0.0.0

这行代码告诉你的操作系统监听所有公开的 IP 。

调试模式

Flask还有一个很实用的调试模式,这在我们测试和编写应用的时候挺实用的,开启调试模式之后,我们每次更改代码它都会自动重载,不需要我们手动反复开启服务了,而且在代码出错时还会提供一个有用的调试器(可以执行任意代码),下面的命令就可以开启调试模式:

$ export FLASK_ENV=development
$ flask run

关于调试,还可以在应用中使用test_request_context()环境管理器来进行单元测试,使用with语句可以绑定一个测试请求,例如:

from flask import request

with app.test_request_context('/hello', method='POST'):
    # now you can do something with the request until the
    # end of the with block, such as basic assertions:
    assert request.path == '/hello'
    assert request.method == 'POST'

0x03 关于路由

之前有提到,使用@app.route()装饰器就可以把一个URL绑定到某个函数上,那个函数的返回值就是显示在页面上的内容,这其实就是Flask的路由方式。(路由是可以叠加的)

(需要注意的是如果指定了路径,比如@app.route('/post/'),一定要在最后加上一个/否则这个post就会被当成一个路径去访问)

同时,路由之中可以使用methods参数来处理不同的HTTP方法(默认只处理GET),以下是一个例子

from flask import request
app = Flask(__name__)

@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        pass
    else:
        pass

URL变量

路由中给出的URL可以使用变量,格式为<converter:variable_name>,变量名可以被作为参数传入处理函数中

string (缺省值) 接受任何不包含斜杠的文本
int 接受正整数
float 接受正浮点数
path 类似 string ,但可以包含斜杠
uuid 接受 UUID 字符串

例如

@app.route('/userinfo/<string:username>')
def userinfo(username):
    return 'Welcome %s' % escape(username)

使用 url_for 构建URL

url_for()可以用来构造指定函数的URL,例如有这样一个路由

@app.route('/login')
def login():
    pass

@app.route('/userinfo/<username>')
def profile(username):
    pass

此时我们如果使用url_for,就可以构造出如下URL:

url_for('login')    # /login
url_for('login', next='/')    # /login?next=/
url_for('profile', username='DiaosSama')    # /userinfo/DiaosSama

动态建立URL的好处就不用多说了,当使用动态变量更改URL时,相比于把URL写死在模板中,动态建立更加方便,需要修改的地方也更少

0x04 页面渲染

作为一个框架,它就一定有渲染html页面的功能,Flask这个框架也不例外

静态文件

想要使用静态文件,比如css或者js的时候,只需要将它们放在/static文件夹下,并使用url_for()就可以生成相应的URL

url_for('static', filename='style.css')    # static/style.css

渲染模板页面

使用render_template()方法就可以渲染模板,只需要提供模板名称和需要作为参数传递给模板的变量就行了,flask中内置了Jinja2模板引擎用以渲染模板,所以一些模板的语法可以在Jinja2的文档中找到

from flask import render_template

@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
    return render_template('hello.html', name=name)

模板文件默认放在templates文件夹中

0x05 重定向和错误

使用 redirect() 函数可以重定向。使用 abort()可以 更早退出请求,并返回错误代码:

from flask import abort, redirect, url_for

@app.route('/')
def index():
    return redirect(url_for('login'))

@app.route('/login')
def login():
    abort(401)
    this_is_never_executed()

上例实际上是没有意义的,它让一个用户从索引页重定向到一个无法访问的页面(401 表示禁止访问)。但是上例可以说明重定向和出错跳出是如何工作的。

缺省情况下每种出错代码都会对应显示一个黑白的出错页面。使用 errorhandler()装饰器可以定制出错页面:

from flask import render_template

@app.errorhandler(404)
def page_not_found(error):
    return render_template('page_not_found.html'), 404

注意 render_template()后面的 404 ,这表示页面对应的出错 代码是 404 ,即页面不存在。缺省情况下 200 表示:一切正常。

0x06 结语

第一部分学习先到这里吧,下一部分的学习着重在处理请求方面,即Flask中的request模块


本博客所有文章除特别声明外,均采用 CC BY-SA 3.0协议 。转载请注明出处!

PE文件格式分析 上一篇
Hadoop学习笔记(三) 下一篇