python flask框架

hello world

from flask import Flask

app = Flask(__name__)
@app.route('/') 

def index(name):
    return 'hello world!'

if __name__ == '__main__':
    app.run()

保存为hello.py,这是flask框架制作的小应用,在命令行中运行python hello.py,
访问 http://127.0.0.1:5000 就会看到hello world!

这里首先引入Flask类,实例化一个对象app,__name__代表这个模块的名字。因为这个模块是直接被运行的,所以此时__name__的值是__main__。然后用route()这个修饰器定义了一个路由,告诉flask如何访问该函数。最后用run()函数使这个应用在服务器上运行起来。

路由

flask框架是通过route()装饰器将一个函数绑定到对应的url上。

例子:

from flask import Flask
app = Flask(__name__)

@app.route('/admin')
def admin():
    return 'helllo admin!'

@app.route('/user')
def user():
    return 'hello user!'

if __name__ == '__main__':
    app.run()

按照上面的方法,运行脚本,访问http://127.0.0.1:5000/admin就会输出hello admin!。访问http://127.0.0.1:5000/user就会得到hello user!。

flask支持在路由上制定参数及参数类型,通过<variable_name>(即:<变量名>)可以标记变量,这个部分将会作为命名参数传递到你的函数,也可以通过<converter:variable_name> (即:<类型转换器:变量名>)指定一个可选的装饰器

实例:

from flask import Flask

app = Flask(__name__)

@app.route('/<name>')
def index(name):
    return 'path %s'% name

if __name__ == '__main__':
    app.run()

运行脚本后,我们访问http://127.0.0.1:5000/user,会看到 path user,当我们访问http://127.0.0.1:5000/user/时会报错,显示Not Found。

实例:

from flask import Flask

app = Flask(__name__)

@app.route('/<int:id>')
def id(id):
    return 'path %d'% id

if __name__ == '__main__':
    app.run()

运行脚本后,我们访问http://127.0.0.1:5000/user时会报错,显示Not Found。当我们访问http://127.0.0.1:5000/123时,会看到path 123,这里说名只能是int类型的即整型的才能访问的到。

类型转换器 作用 占位符标识
缺省(即 :默认) 字符型,不能出现斜线 %s
int 整型 %d
float 浮点型 %f (默认小数点后六位)
path 字符型,可以有斜线 %s

HTTP方法

处理HTTP方法在Flask框架中是使用route装饰器的methods参数设置的。

from flask import request
from flask import Flask
app = Flask(__name__)
@app.route('/login', methods=['GET', 'POST'])

def login():
    if request.method == 'POST':
        return 'POST'
    else:
        return 'GET'

if __name__ == '__main__':
    app.run()

当你请求地址http://localhost:5000/login,”GET”和”POST”请求会返回不同的内容,其他请求方法则会返回405错误。

唯一URL/重定向行为

Flask的URL规则是基于Werkzeug的路由模块。模块背后的思想是基于 Apache 以及更早的 HTTP 服务器主张的先例,保证优雅且唯一的 URL。

from flask import Flask

app = Flask(__name__)

@app.route('/admin/')
def projects():
    return 'The admin page'

@app.route('/user')
def about():
    return 'The user page'

if __name__ == '__main__':
    app.run()

访问第一个路由不带/时,Flask会自动重定向到正确地址。
访问第二个路由时末尾带上/后Flask会直接报404 NOT FOUND错误。

构造url

Flask提供了url_for()方法来快速获取和构造url,方法的第一个参数指向函数名(加过`@app.route`注解的函数),后续的参数对应于要构建的URL变量。
实例:

from flask import Flask,url_for
app = Flask(__name__)
@app.route('/log')

def login():
    return url_for('login')

if __name__ == '__main__':
    app.run()

访问http://localhost:5000/log得到`/log`。解释:返回的是路由地址,`url_for()`方法的第一个参数是路由里的函数名login。

url_for('login')    # 返回/log
url_for('login', id='1')    # 将id作为URL参数,返回/log?id=1
url_for('hello', name='man')    # 适配hello函数的name参数,返回/hello/man
url_for('static', filename='style.css')    # 静态文件地址,返回/static/style.css

Web程序中常常需要处理静态文件,在Flask中需要使用url_for函数并指定static端点名和文件名。在上面的例子中,实际的文件应放在static/文件夹下。

实例:

from flask import Flask,url_for
app = Flask(__name__)
@app.route('/article/<id>/')
def article(id):
    return 'article is detail'

@app.route('/')
def index():
    return url_for("article",id='1')

if __name__ == '__main__':
    app.run(host='10.10.166.142',port='9000',debug=True)

这时访问http://127.0.0.1:5000时返回/article/1/

request对象

from flask import Flask,request,render_template
app = Flask(__name__)
@app.route('/login', methods=['POST', 'GET'])

def login():
    if request.method == 'POST':
        if request.form['user'] == 'admin':
            return 'Admin login successfully!'
        else:
            return 'No such user!'
    title = request.args.get('title', 'Default')
    return render_template('login.html', title=title)

if __name__ == '__main__':
    app.run()

request.args.get()方法则可以获取Get请求URL中的参数,该函数的第二个参数是默认值,当URL参数不存在时,则返回默认值。
templates目录下,添加layout.html文件

<!doctype html>
<title>Hello Sample</title>
<link rel="stylesheet" type="text/css" href="{{ url_for('static', filename='style.css') }}">
<div class="page">
    {% block body %}
    {% endblock %}
</div>

添加login.html

{% extends "layout.html" %}
{% block body %}
<form name="login" action="/login" method="post">
    Hello {{ title }}, please login by:
    <input type="text" name="user">
</form>
{% endblock %}

访问:http://127.0.0.1:5000/login 得到:Hello Default, please login by:输入框,我们get方式传参title=alex 得到:Hello alex, please login by:输入框,我们在输入框中输入admin,得到:Admin login successfully! 如果输入别的则得到No such user!

全局对象 g

flask.g是Flask一个全局对象,g的作用范围,就在一个请求(也就是一个线程)里,它不能在多个请求间共享。你可以在g对象里保存任何你想保存的内容。

构建响应

from flask import Flask,request,session, make_response,render_template
app = Flask(__name__)
@app.route('/login', methods=['POST', 'GET'])

def login():
    if request.method == 'POST':
        pass
    if 'user' in session:
        pass
    else:
        title = request.args.get('title', 'Default')
        response = make_response(render_template('login.html', title=title), 200)
        response.headers['key'] = 'value'
        return response

if __name__ == '__main__':
    app.run()

make_response方法就是用来构建response对象的,第二个参数代表响应状态码,缺省就是200。

会话对象session

会话可以用来保存当前请求的一些状态,以便于在请求之前共享信息。

登入

from flask import Flask,request,render_template,session

app=Flask(__name__)

@app.route('/login', methods=['POST', 'GET'])
def login():
    if request.method == 'POST':
        if request.form['user'] == 'admin':
            session['user']=request.form['user']
            return 'Admin login successfully!'
        else:
            return 'No such user!'
    if 'user' in session:
        return 'Hello %s!'%session['user']
    else:
        title = request.args.get('title', 'Default')
        return render_template('login.html', title=title)
app.secret_key='123456'
if __name__=='__main__':
    app.run()

使用session时一定要设置一个密钥app.secret_key,密钥要尽量复杂,最好使用一个随机数。

登出

from flask import request, session, redirect, url_for

@app.route('/logout')
def logout():
    session.pop('user', None)
    return redirect(url_for('login'))

模板

模板生成

Flask默认使用Jinja2作为模板,默认情况下,模板文件需要放在templates文件夹下。
用 Jinja 模板,只需要使用render_template函数并传入模板文件名和参数名即可。

from flask import render_template

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

hello()函数并不是直接返回字符串,而是调用了render_template()方法来渲染模板。方法的第一个参数hello.html指向你想渲染的模板名称,第二个参数name是你要传到模板去的变量,变量可以传多个。
hello.html代码:

<!Doctype html>
<title>Hello from Flask</title>
{% if name %}
  <h1>Hello {{ name }}!</h1>
{% else %}
  <h1>Hello, World!</h1>
{% endif %}

变量或表达式由{{ }}修饰,而控制语句由{% %}修饰,其他的代码,就是我们常见的HTML。

模板标签

代码块需要包含在{% %}块中

{% extends 'layout.html' %}
{% block title %}主页{% endblock %}
{% block body %}

    <div class="jumbotron">
        <h1>主页</h1>
    </div>

{% endblock %}
  • thinkphp5基础学习

    thinkphp5基础认识在thinkphp5中,无论我们怎么对项目进行更改,最终我们访问的文件只有一个,我们把这种只需要通过访问一个(单个)文件就能实现各种功能需求的设计,叫做『单入口模式』。 在thinkphp中,是通过“入口文件...

    thinkphp5基础学习
  • linux三剑客

    前言之前用一些脚本都经常用到grep,sed,awk。但是一直不太熟悉,今天来学习一下,做个备忘录。 grep格式: grep [OPTIONS] PATTERN [FILE...] grep [OPTIONS] [-e PATTER...

    linux三剑客
  • i春秋2020新春战“疫”网络安全公益赛 web Writeup

    前言这次比赛题目质量挺好的,除啦环境可能有时候有点问题。(就让我遇到了。心态炸了一天。。。)其他都挺好的。 DAY1简单的招聘系统知识点:sql注入的联合注入或盲注存在注册和登陆功能,首先进行注册后登陆进系统,发现有一个模块是管理员才...

    i春秋2020新春战“疫”网络安全公益赛 web Writeup
  • 计算机组成原理学习

    计算机组成原理第一章 计算机系统概论计算机系统的层次结构 冯·诺依曼计算机的特点 计算机由运算器、存储器、控制器、输入设备和输出设备五大部件组成 指令(程序)和数据以二进制同等地位地存储在存储器中,可按址寻访 指令由操作码和地址码组...

    计算机组成原理学习
  • 2019安洵杯+2019广外比赛web部分题解

    2019安洵杯easy_web知识点:MD5强碰撞,命令执行这个题比较简单,看题目发现传入参数img和cmd,然而图片是传入的img参数控制,让我想到ddctf的一道题,然后发现img是通过把文件名进行转十六进制后两次base64编码...

    2019安洵杯+2019广外比赛web部分题解
  • bypass disfunction

    前言PHP 的 disabled_functions主要是用于禁用一些危险的函数防止攻击者执行系统命令。但是有一些绕过方法。这里做个总结。 基本思路有四种绕过 disable_functions 的手法:第一种,攻击后端组件,寻找存在...

    bypass disfunction
  • 2019极客大挑战RCE ME

    题目环境:http://114.116.44.23:40001/ 题目还是老样子。无字母数字rce。知识点其实都有写过,就不说了。详细参见:【RCE提高篇】题目源码: <?php ini_set("display_errors"...

    2019极客大挑战RCE ME
  • RCE提高篇

    前言首先,需要了解一下命令执行的函数,这里推荐几篇文章,来认识这些函数。浅谈eval和assert从底层分析eval和assert的区别命令执行与代码执行的小结巧用命令注入的N种方式命令注入绕过姿势我就不在说这几个东西,大牛们都说的很...

    RCE提高篇
  • buuctf刷题记录(序)

    love math知识点:代码审计,绕waf直接给出源码: <?php error_reporting(0); //听说你很喜欢数学,不知道你是否爱它胜过爱flag if(!isset($_GET['c'])){ sho...

    buuctf刷题记录(序)
  • phar拓展反序列化攻击面

    pharphar扩展提供了一种将整个php应用程序放入名为“phar”(php archive)的单个文件中的方法,以便于分发和安装。除了提供这个服务之外,phar扩展还提供了一个文件格式抽象方法,用于通过phardata类创建和操作...

    phar拓展反序列化攻击面