Flask Cookie介绍

Posted Flask学习笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask Cookie介绍相关的知识,希望对你有一定的参考价值。

HTTP cookies

1.为什么会有cookie

HTTP Cookies 是服务器发送给用户浏览器并保存在本地的一小块数据,它会在浏览器下一次向同一服务器再次发送请求时被携带并发送给服务器.

它的作用是用来告诉服务器两个请求是否来自同一浏览器(如保持用户的登录状态).

这个原因是HTTP 协议本身是无状态的,它并不能区分管理请求和响应.

Flask Cookie介绍
10300
  • 客户端通过 http 协议去连接服务器,服务器并不记录是哪个客户端, 服务器无法区分两次请求是来自同一浏览器还是多个浏览器,这也就意味着浏览器每打开一个标签页访问同一网站,都需要去验证用户名和密码.这显然是不可能的,因此 cookie 技术诞生.

Cookie 具有以下特征:

  1. 从 Web 服务器发向用户的浏览器
  2. Cookie 中的数据是简单的纯文本,不是二进制.
  3. Cookie 被浏览器存储在用户的电脑上(磁盘).
  4. 一个网站只能读取它自己的 Cookie,不能读其他网站甚至域名的.这个安全性由浏览器保证.
  5. Cookie 不会在多个浏览器中共享,换句话说,一个浏览器不能读取存在其他浏览器Cookie,即使是同一域名的也不行.
  6. 根据 HTTP 协议,所有 Cookie 的大小不能超过 4KB.
  7. Web 服务器发给客户端的 Cookie 数量是有限制的.这避免客户端过度消耗磁盘,每个域名大概 20-25 个 Cookie.

它主要作用于以下方面:

  • 认证
  • 追踪用户
  • 个性化(主题,语言选择等)

2.Cookie如何工作

Cookie 最常用用于登录和登出操作.下面以google登陆为例来看实际中如如何登陆的:

  1. 浏览器先向 www.google.com的服务器发送一个 HTTP 请求.通常是一个 POST 请求,包含用户名和密码.
  2. 请求到达服务器后,服务器会验证用户的合法性.如果验证成功,服务器会给浏览器发送一个 Response with cookie(通常是一个 GUID或者任何服务器的唯一标识)
  • Cookie会放置在 Response headSet-Cookie 字段中
  1. 浏览器在收到 Response with cookie 后,会把 Cookie保存在磁盘中(和 Cookie的过期时效有关)
  2. 此后,如果用户在同一浏览器中的新标签页访问 www.google.com,浏览器会在 Response 中自动带上 cookie
  3. google.com服务器在读到这个 cookie时会验证它的合法性.服务器通常都会在内存里维护一个所有它生成的 Cookie 的字典.通常用 sessionID为键, UserID 或者其他标识用户信息的内容作为值.
  4. 在认证完用户后,服务器就可以给用户发送自定义的动态页面.通常都包含该用户的特殊信息(如名字,头像,好友列表,活动订阅等等)

3.创建Cookie

  • 当服务器收到HTTP请求时,服务器可以在ResponseHeader 中添加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.CookieSecureHttpOnly 标记

标记为 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 类似,还有DomainPath指令用于对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主要有三种攻击:

  1. 中间人攻击
  2. XSS跨站脚本攻击
  3. CSRF 跨站请求伪造攻击.

Flask Cookie

1.Flask Request

HTTPRequest 的头部Header 中,包含了一个Cookie的属性.它包含了键值对和过期时间,路径和域等信息.

Flask 中,Cookie设置在Response 类对象上.可以如下设置cookie

  1. 使用 make_response() 函数从视图函数的返回值中获取响应对象.
  2. 使用响应对象的 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

Flask Cookie介绍
10036

点击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.htmluser.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
11045
  • 在打开新标签页访问 blog.kningyuan.club:5000,查看是否有 cookie
11046

4.删除cookie

如果要删除cookie ,可以设置超时时间使浏览器删除cookie .还有一种方法是服务器删除cookie.

@app.route('/del_cookie')  
def del_cookie():  
        response=make_response('delete cookie2')  
        response.delete_cookie('name')  
        return response  
- END -
Flask学习笔记 发起了一个读者讨论 留言板

以上是关于Flask Cookie介绍的主要内容,如果未能解决你的问题,请参考以下文章

Flask Session 介绍

js代码片段: utils/lcoalStorage/cookie

flask客户端测试使用设置cookie参数

Flask 编写http接口api及接口自动化测试

Flask 简单使用

flask-session