Flask Cookie介绍
Posted Flask学习笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask Cookie介绍相关的知识,希望对你有一定的参考价值。
HTTP cookies
1.为什么会有cookie
HTTP Cookies
是服务器发送给用户浏览器并保存在本地的一小块数据,它会在浏览器下一次向同一服务器再次发送请求时被携带并发送给服务器.它的作用是用来告诉服务器两个请求是否来自同一浏览器(如保持用户的登录状态).
这个原因是
HTTP
协议本身是无状态的,它并不能区分管理请求和响应.
客户端通过 http
协议去连接服务器,服务器并不记录是哪个客户端, 服务器无法区分两次请求是来自同一浏览器还是多个浏览器,这也就意味着浏览器每打开一个标签页访问同一网站,都需要去验证用户名和密码.这显然是不可能的,因此cookie
技术诞生.
Cookie
具有以下特征:
从 Web 服务器发向用户的浏览器 Cookie 中的数据是简单的纯文本,不是二进制. Cookie 被浏览器存储在用户的电脑上(磁盘). 一个网站只能读取它自己的 Cookie,不能读其他网站甚至域名的.这个安全性由浏览器保证. Cookie 不会在多个浏览器中共享,换句话说,一个浏览器不能读取存在其他浏览器Cookie,即使是同一域名的也不行. 根据 HTTP 协议,所有 Cookie 的大小不能超过 4KB. Web 服务器发给客户端的 Cookie 数量是有限制的.这避免客户端过度消耗磁盘,每个域名大概 20-25 个 Cookie. 它主要作用于以下方面:
认证 追踪用户 个性化(主题,语言选择等)
2.Cookie
如何工作
Cookie
最常用用于登录和登出操作.下面以
浏览器先向 www.google.com
的服务器发送一个HTTP
请求.通常是一个POST
请求,包含用户名和密码.请求到达服务器后,服务器会验证用户的合法性.如果验证成功,服务器会给浏览器发送一个 Response with cookie
(通常是一个GUID
或者任何服务器的唯一标识)
Cookie
会放置在Response head
的Set-Cookie
字段中
浏览器在收到 Response with cookie
后,会把Cookie
保存在磁盘中(和Cookie
的过期时效有关)此后,如果用户在同一浏览器中的新标签页访问 www.google.com
,浏览器会在Response
中自动带上cookie
google.com
服务器在读到这个cookie
时会验证它的合法性.服务器通常都会在内存里维护一个所有它生成的Cookie
的字典.通常用sessionID
为键,UserID
或者其他标识用户信息的内容作为值.在认证完用户后,服务器就可以给用户发送自定义的动态页面.通常都包含该用户的特殊信息(如名字,头像,好友列表,活动订阅等等)
3.创建Cookie
当服务器收到
HTTP
请求时,服务器可以在Response
的Header
中添加Set-Cookie
选项.浏览器收到
Response with Cookie
后,之后对服务器的每一次请求都通过Cookie
请求头部将Cookie
信息发送给服务器.同时,
Cookie
的过期时间,域,路径,有效期,适用站点都可以根据需要来指定.
1.Set-Cookie
服务器使用
Set-Cookie
来放置到Response
信息中,一个简单的Cookie
类似如下:Set-Cookie:<cookie 名字>=<cookie 值>
同时可以构造多个
Set-Cookie
:HTTP/1.0 200 OK
Content-type: text/html
Set-Cookie: yummy_cookie=choco
Set-Cookie: tasty_cookie=strawberry
2.Session Cookie
Session Cookie
是最简单的Cookie
:当浏览器关闭之后它会被自动删除,也就是说它仅仅在会话期间有效.
Session Cookie
不需要指定过期时间(Expires
)或者有效期(Max-Age
).需要注意的是,有些浏览器提供了会话恢复功能(比如chrome
) ,这种情况下即使关闭了浏览器,Session Cookie
也会被保留.
3.持久性Cookie
指的是指定了过期时间(
Expires
)或者有效期(Max-Age
)的Cookie
.Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT;
注意:使用
Expires
指定的过期时间是格林威治时间,需要用时区计算出自己所在时区的真正过期时间.(比如北京时间+8
)
4.Cookie
的Secure
和HttpOnly
标记
标记为
Secure
的Cookie只应通过被HTTPS
协议加密过的请求发送给服务端.但即便设置了Secure
标记,敏感信息也不应该通过Cookie
传输,因为Cookie
有其固有的不安全性,Secure
标记也无法提供确实的安全保障.从 Chrome 52 和 Firefox 52 开始,不安全的站点
http:
无法使用Cookie的Secure
标记.
HttpOnly
:如果服务器发送的Cookie
不想被客户端的javascript
调用,可以设置HttpOnly
标记.这样做是为了防止跨域脚本攻击(XSS
).Set-Cookie: id=a3fWa; Expires=Wed, 21 Oct 2015 07:28:00 GMT; Secure; HttpOnly
5.Cookie
的作用域
和
Expires
类似,还有Domain
和Path
指令用于对Cookie
指定作用域.
Domain
:指定了哪些主机可以接受Cookie
,不指定默认是当前主机(比如www.google.com
),不包含子域名.如果指定了Domain
,则包含子域名.(比如指定Domain=google.com
,cookie
可以用于gmail.google.com
子域名).
Path
:指定了主机下哪些路径可以接受Cookie
(路径必须存在于请求URL中).以字符%x2F
("/") 作为路径分隔符,子路径也会被匹配.例如,设置Path=/docs
,则以下路径都会匹配.
/docs
/docs/web/
/docs/web/http
6.SameSite Cookies
允许服务器要求某个
Cookie
在跨站请求中不会被发送,用来阻止伪造攻击(CSRF
)
4.Cookie
的限制
大小:每个最大 4K
数量:针对每个域名, Cookie
的数量都有限制,这个限制是浏览器设置的,不是HTTP
协议.域名:服务器只能设置自己域名的 Cookie
访问: HTTP Cookie
可以被JavaScript
读取.
5.安全
由于
Cookie
的特质,它存在着一些不安全的漏洞,当机器处于不安全环境时,切记不能通过HTTP Cookie存储,传输敏感信息.针对
Cookie
主要有三种攻击:
中间人攻击 XSS
跨站脚本攻击CSRF
跨站请求伪造攻击.
Flask Cookie
1.Flask Request
HTTP
的Request
的头部Header
中,包含了一个Cookie
的属性.它包含了键值对和过期时间,路径和域等信息.在
Flask
中,Cookie
设置在Response
类对象上.可以如下设置cookie
使用 make_response()
函数从视图函数的返回值中获取响应对象.使用响应对象的 set_cookie()
函数来存储cookie
的基本信息(键值对,过期时间,路径,域)比如,新生成一个项目(参考代码:https://github.com/ningwenyan/demo_code/tree/master/flask_demo_code/T17):
flask_cookie_demo1
├── app.py
├── static
└── templates
├── login.html
└── user.html
login.html
<form action="" method="POST">
<table>
<tr>
<td>Name</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>Password</td>
<td><input type="password" name="password"></td>
</tr>
<tr>
<td><input type="submit" value="Login"></td>
<td></td>
</tr>
</table>
</form>
user.html
<p>This is {{ username }}.<a href="/getcookies/?name={{ username }}">click me</a> </p>
app.py
from flask import Flask
from flask import make_response
from flask import render_template,request
from uuid import uuid4
app = Flask(__name__)
app.config.update({
'DEBUG':True,
'TEMPLATES_AUTO_RELOAD':True
})
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/login/',methods=['POST','GET'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
name = request.form.get('name')
password = request.form.get('password')
# cookie是设置在 Response 响应对象上的,普通的字符串也是通过 response()方法返回的
# 如果要显式的返回,可以使用 make_response函数
# 假设用户为 ning,返回的应该是个性化窗口 ning.html
id = str(uuid4())
resp = make_response(render_template('user.html', username=name))
# 只设置 key,value 键值对
resp.set_cookie(name,id)
return resp
@app.route('/getcookies/')
def get_cookie():
name = request.args.get('name')
cookie1 = request.cookies.get(name)
print(name)
return cookie1
if __name__ == '__main__':
app.run()这里显式的返回了
Response
对象,使用make_response()
函数进行构造.并把set_cookie
传递到Response
信息中.存储的键值对是用户名和唯一的uuid
.使用浏览器访问
http://127.0.0.1:5000/login/
提交后可以查看cookie
点击
click me
,可以访问到cookie
的值.
2.set_cookie()
方法
Flask
中的response
对象都有set_cookie()
方法,它可以设置Cookie
的基本信息.def set_cookie(
self,
key, # cookie 的名称
value="", # cookie 的值
max_age=None, # 秒数,cookie在多少秒后时效
expires=None, # datetime 对象, Unix时间戳
path="/", # cookie 作用于网站的路径,默认为 全覆盖
domain=None, # domain=''.example '',可以访问所有的子域名
secure=False, # True,只能用https. False=>http
httponly=False, # 禁止 JavaScript 访问 Cookie
samesite=None, # 限制 cookie 的范围
):
3.结合蓝图设置子域名
参考代码:https://github.com/ningwenyan/demo_code/tree/master/flask_demo_code/T18
主域名和子域名应该添加到
hosts
文件中$ vim /etc/hosts
192.168.0.110 kningyuan.club
192.168.0.110 blog.kningyuan.club生成如下项目目录
flask_cookie_demo2
├── app.py
├── blueprint_model
│ ├── blog.py
│ ├── __init__.py
├── static
└── templates
├── login.html
└── user.html
login.html
和user.html
同上.
blog.py
"""
设置蓝图子域名
"""
from flask import Blueprint
# 实例化
bp = Blueprint('blog', __name__,subdomain='blog')
@bp.route('/')
def index():
return '123'
app.py
from flask import Flask
from blueprint_model import blog
from flask import make_response,request,render_template
from uuid import uuid4
app = Flask(__name__)
app.config.update({
'DEBUG':True,
'TEMPLATES_AUTO_RELOAD':True,
"SERVER_NAME": "kningyuan.club:5000" # 设置网站主域名
})
@app.route('/')
def hello_world():
return 'Hello World!'
@app.route('/login/',methods=['POST','GET'])
def login():
if request.method == 'GET':
return render_template('login.html')
else:
name = request.form.get('name')
password = request.form.get('password')
# cookie是设置在 Response 响应对象上的,普通的字符串也是通过 response()方法返回的
# 如果要显式的返回,可以使用 make_response函数
# 假设用户为 ning,返回的应该是个性化窗口 ning.html
id = str(uuid4())
resp = make_response(render_template('user.html', username=name))
# 只设置 key,value 键值对
# 域名记得加端口号,除非你是80端口
resp.set_cookie(name,id,domain='.kningyuan.club:5000',max_age=200)
return resp
# 注册蓝图
app.register_blueprint(blog.bp)
if __name__ == '__main__':
app.run(host='192.168.0.110')过期时间除了设置
max-age
外,也可以设置expires
,它指定的是datetime
数据类型.需要注意的是,它是格林威治标准时间,如果是在中国,需要换算时区,也就是和你真正设定的时间少8小时.# 想要指定的时间
expires = datetime(year=2018,month=7,day=14,hour=16,minute=29,second=0)
# 真正设置的时间.
expires = datetime(year=2018, month=7, day=14, hour=8, minute=29, second=0)验证:
首先使用浏览器访问 kningyuan.club:5000/login/
,登录网站,成功获取到cookie
在打开新标签页访问 blog.kningyuan.club:5000
,查看是否有cookie
4.删除cookie
- END -如果要删除
cookie
,可以设置超时时间使浏览器删除cookie
.还有一种方法是服务器删除cookie
.@app.route('/del_cookie')
def del_cookie():
response=make_response('delete cookie2')
response.delete_cookie('name')
return response
以上是关于Flask Cookie介绍的主要内容,如果未能解决你的问题,请参考以下文章