HTTP是无状态协议,也就是说,在一次请求响应结束之后,服务器不会留下任何关于对方状态的信息。但是某些信息有事我们必须要记住的,例如用户的登陆状态,这样可以根据状态返回不同的响应。这个地方就需要用到cookie技术。cookie指web服务器为了存储某些数据而保存在浏览器里的小型文本数据。浏览器会第一时间保存它,并在下一次请求的时候携带该数据。cookie通常被用来进行用户会话管理,保存用户的个性化设信息以及和收集用户浏览数据以分析用户行为。
在flask中,想在响应之中添加一个cookie,最方便的方法就是使用Response类提供的set_cookie()方法。
# 响应时携带cookie
from flask import Flask, make_response, request, rediect, url_for
@app.route('/set/<name>')
def set(name)
response = make_response(rediect(url_for('hello')))
response.set_cookie("name", name)
return response
# 请求时获取cookie
@app.route('/')
@app.route('/hello')
def hello():
name = request.args.get("name")
if name is None:
name = request.cookies.get("name", "zhang"))
return name
set_cookie()方法的参数
属性 | 说明 |
---|---|
key | cookie键 |
value | cookie值 |
max_age | cookie被保存的时间数,默认为关闭浏览器时过期 |
expires | 具体过期时间 |
path | 限制cookie在给定路径可用,默认为整个域名 |
domain | 设置可用域名 |
secure | 如果设为true, 只有https协议可用 |
httponly | 如果设为true,禁止客户端js获取 |
Cookie在web程序中发挥了很大作用,但他有一个致命缺点,就是保存在客户端,可以被手动添加和修改,这样的话会带来一些安全问题。于是我们需要对敏感的cookie进行加密,flask提供了session对象来讲cookie加密保存。
app.secret_key = "SDADADAIDHAUHUIEHRUIA"
更安全的办法是将secret_key值写入系统环境变量或.env文件中。
import os
app.secret_key = os.getenv("SECRET_KEY", "sadadadadfeea")
from flask import redirect, session, url_for, reqest, session
@app.route('/login')
def login():
session['login_in'] = True # 写入session
return redirect(url_for('hello')))
@app.route('/')
@app.route('/hello')
def hello():
# 根据用户认证状态返回不同的内容
if "login_in: in session:
return "Authentocated"
else:
return "Not Authentocated"
@app.route('/logout')
def logout()
if "login_in" in session:
session.pop("login_in") # 删除写入数据
return rediect(url_for("hello"))
默认情况下,session cookie会在用户关闭浏览器时删除。我们可以通过session.permanent属性设为True来延长有效期,也可以通过配置PERMANENT_SESSION_LIFETIME设置有效期。尽管session对象会对cookie进行签名加密,但这只能保证内容不被篡改,加密后的数据借助工具还是能够读取,因此,绝对不能再session中存储敏感信息。
Flask中有两种上下文,程序上下文和请求上下文。
Flask中的上下文变量
变量名 | 上下文类别 | 说明 |
---|---|---|
current_app | 程序上下文 | 指向处理请求的当前程序实例 |
g | 程序上下文 | 替代Python的全局变量用法,确保仅在当前请求中可用。用于替代全局数据,每次请求都会重设。 |
request | 请求上下文 | 封装客户发出的请求报文数据 |
session | 请求上下文 | 用于记住请求之间的数据,通过签名的cookie实现 |
from flask imort g
@app.before_request
def get_name():
g.name = request.args.get('name')
# 因为g存储在程序上下文中,且每次都会随请求重设。我们可以通过它来结合请求钩子来保存每个请求处理前所需要的全局变量,比如登入的用户对象、数据库连接等。
在下面情况下,Flask会自动激活上下文:
from app import app
from flask import current_app
# 使用with语句执行上下文操作
with app.app_context():
print(current_app.name)
# 显式的使用push()方法推送(激活)上下文,在执行完操作时使用pop()方法销毁
app_ctx = app.app_context()
app_ctx.push()
print(current_app.name)
app_ctx.pop()
# 通过test_request_context()临时创建上下文
with app.test_request_context('/hello'):
print(request.method)
flask为上下文提供了一个teardown_appcontext()钩子,使用它注册的回调函数会在程序上下文被销毁时调用,而且通常也会在请求上下文被销毁时调用。
# 在每个请求处理结束后销毁数据库连接
@app.teardown_appcontext
def teardown_db(exception):
db.close()