python-flask模块学习

0x00 前言

最近想接触一下python作为后端的环境,所以准备从flask模块开始学习,记录一下用法,当作笔记。

0x01 flask

Flask是一个使用 Python 编写的轻量级 Web 应用框架。其 WSGI 工具箱采用 Werkzeug ,模板引擎则使用 Jinja2 。Flask使用 BSD 授权。因为它使用简单的核心,用 extension 增加其他功能。Flask没有默认使用的数据库、窗体验证工具。

0x02 安装

安装只需在具有python环境的计算机命令行中,输入

1
pip install flask

0x03 基础步骤

  • 我们在使用flask时,必须先要导入库,即

    1
    from flask import Flask
  • 接下来,我们创建一个该类的实例,第一个参数是应用模块或者包的名称。如果使用单一的模块,就使用name

    1
    app = Flask(__name__)
  • 然后,我们使用 route() 装饰器告诉 Flask 什么样的URL 能触发我们的函数。根目录为:

    1
    @app.route("/")
  • 这个函数的名字也在生成 URL 时被特定的函数采用,这个函数返回我们想要显示在用户浏览器中的信息。如:

    1
    2
    def hello():
    return "Hello World!"
  • 最后用 run() 函数来让应用运行在本地服务器上。 其中 if name == ‘main‘: 确保服务器只会在该脚本被 Python 解释器直接执行的时候才会运行,而不是作为模块导入的时候。即:

    1
    2
    if __name__ == "__main__":
    app.run()

这是最基础的操作所需要的五步,组合起来就是:

1
2
3
4
5
6
7
8
9
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"
if __name__ == "__main__":
app.run()

然后在这个.py文件的目录下,打开命令行,使用python xxx.py的方式运行,就会部署到本地服务器的5000端口,我们通过浏览器访问127.0.0.1:5000,就会看到web页面的输出。

0x04 基础函数

设置公网访问

web服务打开时默认是只能通过本机访问的,如果想要通过外网访问,就得先禁用了 debug 然后修改调用 run() 的方法使服务器公开。

实例:

1
app.run(host='0.0.0.0')

设置路由

上面的基础步骤已经提到,由route()函数来设置访问的url,如果我们有多个函数,就可以分别用route()装饰器将不同的函数绑定到不同的url上。

实例

1
2
3
4
5
6
7
8
9
10
11
@app.route('/')
def index():
return 'Index Page'
@app.route('/hello')
def hello():
return 'Hello World'
@app.route('/test')
def test():
return 'Test'

路径变量

路径变量的意思就如同它的名字一样,路径中的一部分是可以改变的,主要用于受变量影响的可变路径,用法是/path/,并且在变量之前还可以使用转换器来改变数据类型

转换器 作用
string 默认选项,接受除了斜杠之外的字符串
int 接受整数
float 接受浮点数
path 和string类似,不过可以接受带斜杠的字符串
any 匹配任何一种转换器
uuid 接受UUID字符串

实例:

1
2
3
4
5
6
7
8
9
@app.route('/user/<username>')
def show_user_profile(username):
# show the user profile for that user
return 'User %s' % username
@app.route('/post/<int:post_id>')
def show_post(post_id):
# show the post with the given id, the id is an integer
return 'Post %d' % post_id

构造URL

flask中可以用 url_for(‘方法名’) 来给指定的函数构造 URL。主参数是方法名,可以额外传入对应 URL 规则的变量部分的命名参数。

实例:

1
2
url_for('index')
url_for('user', username='jack')

HTTP方法

HTTP (与 Web 应用会话的协议)有许多不同的访问 URL 方法。默认情况下,路由只回应 GET 请求,但是通过 route() 装饰器传递 methods 参数可以改变这个行为。用法是app.route(‘/login’, methods=[‘GET’, ‘POST’])

实例:

1
2
3
4
5
6
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
do_the_login()
else:
show_the_login_form()

静态文件

动态 web 应用也会需要静态文件,通常是 CSS 和 JavaScript 文件。只要在你的包中或是模块的所在目录中创建一个名为 static 的文件夹,在应用中使用 /static 即可访问。

实例:

1
url_for('static', filename='style.css')

调试模式

如果你启用了调试支持,服务器会在代码修改后自动重新载入,并在发生错误时提供一个相当有用的调试器。

实例:

1
2
app.debug = True
app.run()

1
app.run(debug=True)

URL “/”重定向

如果设置route(‘/xxx/‘)访问url时如果结尾带了一个反斜杠,就会自动重定向到不带反斜杠的url中,如果不设置反斜杠,就不会重定向,而是返回一个404错误。

实例:

1
2
3
@app.route('/about/')
def about():
return 'The about page'

模板渲染

Flask 配备了 Jinja2 模板引擎,python可以通过 render_template() 方法来渲染模板。只需将模板名和关键字的参数传入模板的变量。

实例:

1
2
3
4
5
6
from flask import render_template
@app.route('/hello/')
@app.route('/hello/<name>')
def hello(name=None):
return render_template('hello.html', name=name)

文件上传

用 Flask 处理文件上传,首先要确保在 HTML 表单中设置 enctype=”multipart/form-data”,已上传的文件存储在内存或是文件系统中一个临时的位置。可以通过请求对象的 files 属性访问它们。每个上传的文件都会存储在这个字典里。它表现近乎为一个标准的 Python file 对象,但它还有一个 save() 方法,这个方法允许你把文件保存到服务器的文件系统上。

实例:

1
2
3
4
5
6
7
8
from flask import request
@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
f = request.files['the_file']
f.save('/var/www/uploads/uploaded_file.txt')
...

Cookies

python flask可以通过 cookies 属性来访问 Cookies,用响应对象的 set_cookie 方法来设置 Cookies。请求对象的 cookies 属性是一个内容为客户端提交的所有 Cookies 的字典。

实例:

读取cookies

1
2
3
4
5
from flask import request
@app.route('/')
def index():
username = request.cookies.get('username')

写入cookies

1
2
3
4
5
6
7
from flask import make_response
@app.route('/')
def index():
resp = make_response(render_template(...))
resp.set_cookie('username', 'the username')
return resp

重定向和错误

flask可以用 redirect() 函数把用户重定向到其它地方。放弃请求并返回错误代码,用 abort() 函数。

实例:

1
2
3
4
5
6
7
8
9
10
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()

日志记录

Flask预置了日志系统。在我们需要日志记录功能时,只需使用logger函数即可。

实例

1
2
3
app.logger.debug('A value for debugging')
app.logger.warning('A warning occurred (%d apples)', 42)
app.logger.error('An error occurred')

session

flask除请求对象之外,还有一个 session 对象。它允许你在不同请求间存储特定用户的信息。它是在 Cookies 的基础上实现的,并且对 Cookies 进行密钥签名。要使用会话,需要设置一个密钥。

实例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
from flask import Flask, session, redirect, url_for, escape, request
app = Flask(__name__)
@app.route('/')
def index():
if 'username' in session:
return 'Logged in as %s' % escape(session['username'])
return 'You are not logged in'
@app.route('/login', methods=['GET', 'POST'])
def login():
if request.method == 'POST':
session['username'] = request.form['username']
return redirect(url_for('index'))
return '''
<form action="" method="post">
<p><input type=text name=username>
<p><input type=submit value=Login>
</form>
'''
@app.route('/logout')
def logout():
# remove the username from the session if it's there
session.pop('username', None)
return redirect(url_for('index'))
# set the secret key. keep this really secret:
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'

0x05 总结

对浅显基础的知识进行学习,虽然对开发能力提升不大,但是有的时候遇到一些python后端或者需要搭建python后端漏洞环境进行测试时,如果没有接触过相关函数就会力不从心,对这些模块略微了解并总结一下,在之后遇到的时候就可以更熟练的进行审计或搭建。

之后在遇到很重要的模块或者语言时,也要通过同样的方式总结一遍,等用到的时候就可以很快的入门。