「必需知道」实用,完整的http cookie指南 -凯发k8国际官网
- 美国研究生
- 2022-02-17
- 231
web 开发中的 cookie 是什么?cookie 是后端可以存储在用户浏览器中的小块数据美国读金融gre gmt。 cookie 最常见用例包括用户跟踪,个性化以及身份验证。
cookies 具有很多隐私问题,多年来一直受到严格的监管美国读金融研究生gre gmt。
在本文中,主要侧重于技术方面:学习如何在前端和后端创建,使用 。
后端配置后端示例是flask编写的美国读金融研究生gre gmt。如果你想跟着学习,可以创建一个新的python虚拟环境,移动到其中并安装flask
mkdir cookies && cd $_python3 -m venv venvsource venv/bin/activatepip install flask在项目文件夹中创建一个名为flask app.py的新文件,并使用本文的示例在本地进行实验美国读金融研究生gre gmt。
谁创建 cookies ?首先美国读金融研究生gre gmt,cookies 从何而来?谁创建 cookies ?
虽然可以使用document.cookie在浏览器中创建 cookie,但大多数情况下,后端的责任是在将响应客户端请求之前在请求中设置 cookie美国读金融研究生gre gmt。
后端是指可以通过以下方式创建 cookie:
后端实际应用程序的代码(python、javascript、php、java)响应请求的web服务器(nginx美国读金融研究生gre gmt,apache)后端可以在 ,它是由键/值对以及可选属性组成的相应字符串:
set-cookie: myfirstcookie=somecookievalue什么时候需要创建 cookie?这取决于需求美国读金融研究生gre gmt。
cookie 是简单的字符串美国读金融研究生gre gmt。在项目文件夹中创建一个名为flask_app.py的python文件,并输入以下内容:
from flask import flask, make_responseapp = flask(__name__)@app.route("/index/", methods=["get"])def index(): response = make_response("here, take some cookie!") response.headers["set-cookie"] = "myfirstcookie=somecookievalue" return response然后运行应用程序:
flask_env=development flask_app=flask_app.py flask run当该应用程序运行时,用户访问。
(127.0.0.1:5000是开发中的 flask 应用程序的默认侦听地址/端口)美国读金融研究生gre gmt。
set-cookie标头是了解如何创建cookie的关键:
response.headers["set-cookie"] = "myfirstcookie=somecookievalue"大多数框架都有自己设置 cookie 的方法,比如flask的set_cookie()美国读金融研究生gre gmt。
如何查看 cookies ?访问:
或者可以在开发人员工具中选中storage选项卡美国读金融研究生gre gmt。单击cookie,会看到 cookie 具体的内容:
在命令行上美国读金融研究生gre gmt,还可以使用curl查看后端设置了哪些 cookie
curl -i 保存到文件中以供以后使用:
curl -i :
curl -i 。
set-cookie: myfirstcookie=somecookievalue; 。
从现在开始,为方便起见,使用flask的 response.set_cookie() 在后端上创建 cookie美国读金融研究生gre gmt。
我有一个 cookie,现在怎么办?你的浏览器得到一个 cookie美国读金融研究生gre gmt。现在怎么办呢?一旦有了 cookie,浏览器就可以将cookie发送回后端。
这有许多用途发如:用户跟踪、个性化,以及最重要的身份验证美国读金融研究生gre gmt。
例如美国读金融研究生gre gmt,一旦你登录网站,后端就会给你一个cookie:
set-cookie: userid=sup3r4n0m-us3r-1d3nt1f13r为了在每个后续请求中正确识别 我们的身份美国读金融研究生gre gmt,后端会检查来自请求中浏览器的 cookie
要发送cookie美国读金融研究生gre gmt,浏览器会在请求中附加一个cookie标头:
cookie: userid=sup3r4n0m-us3r-1d3nt1f13rcookie 可以设置过期时间: max-age 和 expires默认情况下,cookie 在用户关闭会话时即关闭浏览器时过期美国读金融研究生gre gmt。要持久化cookie,我们可以通过expires或max-age属性
set-cookie: myfirstcookie=somecookievalue; expires=tue, 09 jun 2020 15:46:52 gmt; max-age=1209600注意:max-age优先于expires美国读金融研究生gre gmt。
cookie的作用域是网站路径: path 属性考虑该后端,该后端在访问:
from flask import flask, make_response, requestapp = flask(__name__)@app.route("/", methods=["get"])def index(): response = make_response("here, take some cookie!") response.set_cookie(key="id", value="3db4adj3d", path="/about/") return response@app.route("/about/", methods=["get"])def about(): print(request.cookies) return "hello world!"@app.route("/contact/", methods=["get"])def contact(): print(request.cookies) return "hello world!"运行该应用程序:
flask_env=development flask_app=flask_app.py flask run在另一个终端中美国读金融研究生gre gmt,如果我们与根路由建立连接,则可以在set-cookie中看到cookie:
curl -i 属性:
set-cookie: id=3db4adj3d; path=/about//about/ 路由并保存 cookit
curl -i ,可以看到:
immutablemultidict([('id', '3db4adj3d')])127.0.0.1 - - [27/may/2020 11:27:55] "head /about/ / 路由:
url -i ,可以看到:
immutablemultidict([])127.0.0.1 - - [27/may/2020 11:29:00] "head /contact/ 不能被发送到另一个不相关的路径,即使这两个路径位于同一域中。
这是cookie权限的第一层美国读金融研究生gre gmt。
在cookie创建过程中省略path时,浏览器默认为/美国读金融研究生gre gmt。
cookie 的作用域是域名: domain 属性cookie 的 domain 属性的值控制浏览器是否应该接受cookie以及cookie返回的位置美国读金融研究生gre gmt。
让我们看一些例子美国读金融研究生gre gmt。
主机不匹配(错误的主机)查看 :
set-cookie: coookiename=wr0ng-d0m41n-c00k13; domain=api.valentinog.com这里的 cookie 来自serene-bastion-01422.herokuapp.com,但是domain属性具有api.valentinog.com美国读金融研究生gre gmt。
浏览器没有其他选择来拒绝这个 cookie美国读金融研究生gre gmt。比如 chrome 会给出一个警告(firefox没有)
主机不匹配(子域名)查看 :
set-cookie: coookiename=wr0ng-subd0m41n-c00k13; domain=secure-brushlands-44802.herokuapp.com这里的 cookie 来自serene-bastion-01422.herokuapp.com,但**“domain”**属性是secure-brushlands-44802.herokuapp.com美国读金融研究生gre gmt。
它们在相同的域上,但是子域名不同美国读金融研究生gre gmt。同样,浏览器也拒绝此cookie:
主机匹配(整个域)查看 :
set-cookie: cookiename=d0m41n-c00k13; domain=valentinog.com此cookie是使用 nginx add_header在web服务器上设置的:
add_header set-cookie "cookiename=d0m41n-c00k13; domain=valentinog.com";这里使用 nginx 中设置cookie的多种方法美国读金融研究生gre gmt。cookie 是由 web 服务器或应用程序的代码设置的,对于浏览器来说无关紧要。
重要的是 cookie 来自哪个域美国读金融研究生gre gmt。
在此浏览器将愉快地接受cookie,因为domain中的主机包括cookie所来自的主机美国读金融研究生gre gmt。
换句话说,valentinog.com包括子域名。
同时,对valentinog.com的新请求,cookie 都会携带着,以及任何对valentinog.com子域名的请求美国读金融研究生gre gmt。
这是一个附加了cookie的 www 子域请求:
下面是对另一个自动附加cookie的子域的请求
cookies 和公共后缀列表查看 :
set-cookie: coookiename=d0m41n-c00k13; domain=herokuapp.com这里的 cookie 来自serene-bas-01422.herokuapp.com,domain 属性是herokuapp.com美国读金融研究生gre gmt。浏览器在这里应该做什么
你可能认为serene-base-01422.herokuapp.com包含在herokuapp.com域中,因此浏览器应该接受cookie美国读金融研究生gre gmt。
相反,它拒绝 cookie,因为它来自公共后缀列表中包含的域美国读金融研究生gre gmt。
public suffix list(公共后缀列表)美国读金融研究生gre gmt。此列表列举了顶级域名和开放注册的域名。浏览器禁止此列表上的域名被子域名写入cookie。
主机匹配(子域)查看 :
set-cookie: coookiename=subd0m41n-c00k13当域在cookie创建期间被省略时美国读金融研究生gre gmt,浏览器会默认在地址栏中显示原始主机,在这种情况下,我的代码会这样做:
response.set_cookie(key="coookiename", value="subd0m41n-c00k13")当 cookie 进入浏览器的 cookie 存储区时美国读金融研究生gre gmt,我们看到已应用domain :
现在美国读金融研究生gre gmt,我们有来自serene-bastion-01422.herokuapp.com 的 cookie, 那 cookie 现在应该送到哪里?
如果你访问 随请求一起出现:
但是美国读金融研究生gre gmt,如果访问herokuapp.com,则 cookie 不会随请求一起出现:
概括地说美国读金融研究生gre gmt,浏览器使用以下启发式规则来决定如何处理cookies(这里的发送者主机指的是你访问的实际网址):
如果“domain”中的域或子域与访问的主机不匹配美国读金融研究生gre gmt,则完全拒绝 cookie如果 domain 的值包含在公共后缀列表中,则拒绝 cookie如果domain 中的域或子域与访问在主机匹配,则接受 cookie一旦浏览器接受了cookie,并且即将发出请求,它就会说:
如果请求主机与我在domain中看到的值完全匹配,则会回传 cookie如果请求主机是与我在“domain”中看到的值完全匹配的子域,则将回传 cookie如果请求主机是sub.example.dev之类的子域,包含在example.dev之类的 domain 中,则将回传 cookie如果请求主机是例如example.dev之类的主域,而 domain 是sub.example.dev之类,则不会回传cookie美国读金融研究生gre gmt。domain 和 path 属性一直是 cookie 权限的第二层。
cookies可以通过ajax请求传递cookies 可以通过ajax请求传播美国读金融研究生gre gmt。ajax 请求是使用 js (xml请求,用于获取数据并将其发送回后端。
考虑 flask的另一个示例美国读金融研究生gre gmt,其中有一个模板,该模板又会加载 js 文件:
from flask import flask, make_response, render_templateapp = flask(__name__)@app.route("/", methods=["get"])def index(): return render_template("index.html")@app.route("/get-cookie/", methods=["get"])def get_cookie(): response = make_response("here, take some cookie!") response.set_cookie(key="id", value="3db4adj3d") return response以下是 templates/index.html 模板:
const button = document.getelementsbytagname("button")[0];button.addeventlistener("click", function() { getacookie();});function getacookie() { fetch("/get-cookie/") .then(response => { // make sure to check response.ok in the real world! return response.text(); }) .then(text => console.log(text));}当访问中。
对 flask 应用程序进行一些更改美国读金融研究生gre gmt,多加一个路由:
from flask import flask, make_response, request, render_template, jsonifyapp = flask(__name__)@app.route("/", methods=["get"])def index(): return render_template("index.html")@app.route("/get-cookie/", methods=["get"])def get_cookie(): response = make_response("here, take some cookie!") response.set_cookie(key="id", value="3db4adj3d") return response@app.route("/api/cities/", methods=["get"])def cities(): if request.cookies["id"] == "3db4adj3d": cities = [{"name": "rome", "id": 1}, {"name": "siena", "id": 2}] return jsonify(cities) return jsonify(msg="ops!")另外美国读金融研究生gre gmt,调整一下 js 代码,用于下请求刚新增的路由:
const button = document.getelementsbytagname("button")[0];button.addeventlistener("click", function() { getacookie().then(() => getdata());});function getacookie() { return fetch("/get-cookie/").then(response => { // make sure to check response.ok in the real world! return promise.resolve("all good, fetch the data"); });}function getdata() { fetch("/api/cities/") .then(response => { // make sure to check response.ok in the real world! return response.json(); }) .then(json => console.log(json));当访问请求。
在浏览器的控制台中,可以看到请求回来 的数据美国读金融研究生gre gmt。另外,在开发者工具的network选项卡中,可以看到一个名为cookie的头,这是通过ajax请求传给后端。
只要前端与后端在同一上下文中,在前端和后端之间来回交换cookie就可以正常工作:我们说它们来自同源美国读金融研究生gre gmt。
这是因为默认情况下,fetch 仅在请求到达触发请求的来源时才发送凭据,即 cookie美国读金融研究生gre gmt。
cookie 不能总是通过ajax请求传递考虑另一种情况美国读金融研究生gre gmt,在后端独立运行,可以这样启动应用程序:
flask_env=development flask_app=flask_app.py flask run现在美国读金融研究生gre gmt,在 flask 应用程序之外的其他文件夹中,创建index.html:
button.addeventlistener("click", function() { getacookie().then(() => getdata());});function getacookie() { return fetch(",从终端运行:
npx serve此命令为您提供了要连接的本地地址/端口,例如。访问页面并尝试在浏览器控制台打开的情况下单击按钮。在控制台中,可以看到:
cross-origin request blocked: the same origin policy disallows reading the remote resource at 的限制。
处理 corscors 是一个 w3c 标准,全称是“跨域资源共享”(cross-origin resource sharing)美国读金融研究生gre gmt。它允许浏览器向跨域的服务器,发出xml 只能同源使用的限制。
整个 cors 通信过程,都是浏览器自动完成,不需要用户参与美国读金融研究生gre gmt。对于开发者来说,cors 通信与普通的 ajax 通信没有差别,代码完全一样。浏览器一旦发现 ajax 请求跨域,就会自动添加一些附加的头信息,有时还会多出一次附加的请求,但用户不会有感知。因此,实现 cors 通信的关键是服务器。只要服务器实现了 cors 接口,就可以跨域通信。
默认情况下,除非服务器设置了access-control-allow-origin的特定。
要解决此第一个错误美国读金融研究生gre gmt,我们需要为flask配置cors:
pip install flask-cors然后将 cors 应用于 flask:
from flask import flask, make_response, request, render_template, jsonifyfrom flask_cors import corsapp = flask(__name__)cors(app=app)@app.route("/", methods=["get"])def index(): return render_template("index.html")@app.route("/get-cookie/", methods=["get"])def get_cookie(): response = make_response("here, take some cookie!") response.set_cookie(key="id", value="3db4adj3d") return response@app.route("/api/cities/", methods=["get"])def cities(): if request.cookies["id"] == "3db4adj3d": cities = [{"name": "rome", "id": 1}, {"name": "siena", "id": 2}] return jsonify(cities) return jsonify(msg="ops!")现在尝试在浏览器控制台打开的情况下再次单击按钮美国读金融研究生gre gmt。在控制台中你应该看到
cross-origin request blocked: the same origin policy disallows reading the remote resource at 。
你可以通过查看 “network” 标签中的请求来确认,没有发送此类cookie:
为了在不同来源的fetch请求中包含cookie,我们必须提credentials 标志(默认情况下,它是相同来源)美国读金融研究生gre gmt。
如果没有这个标志美国读金融研究生gre gmt,fetch 就会忽略 cookie,可以这样修复:
const button = document.getelementsbytagname("button")[0];button.addeventlistener("click", function() { getacookie().then(() => getdata());});function getacookie() { return fetch(" 中:
fetch("传输回后端
fetch(",我们还需要在后端修复另一个错误:
cross-origin request blocked: the same origin policy disallows reading the remote resource at 。
cors(app=app, supports_credentials=true)要点:为了使cookie在不同来源之间通过ajax请求传递美国读金融研究生gre gmt,可以这样做:
credentials: "include" 用于前端的 fetch 请求中access-control-allow-credentials 和 access-control-allow-origin 用于后端cookie可以通过ajax请求传递,但是它们必须遵守我们前面描述的域规则美国读金融研究生gre gmt。
cookie 的 secure 属性secure 属性是说如果一个 cookie 被设置了secure=true,那么这个cookie只能用协议中发送。
可以这样设置 secure 属性
response.set_cookie(key="id", value="3db4adj3d", secure=true)如果要在真实环境中尝试美国读金融研究生gre gmt,请可以运行以下命令,并注意curl在此处是不通过:
curl -i 中:
curl -i 文件:
serene-bastion-01422.herokuapp.com false / true 0不要被secure欺骗:浏览器通过。
因为带有 secure 的 cookie 一般也不用于传输敏感数据.
cookie 的 。
xss 全称cross sitescript,跨站脚本攻击,是web程序中常见的漏洞,xss属于被动式且用于客户端的攻击方式,所以容易被忽略其危害性美国读金融研究生gre gmt。其原理是攻击者向有xss漏洞的网站中输入(传入)恶意的html代码,当其它用户浏览该网站时,这段html代码会自动执行,从而达到攻击的目的。如,盗取用户cookie、破坏页面结构、重定向到其它网站等。
如果有设置 看起来是这样的:
set-cookie: "id=3db4adj3d; 中
response.set_cookie(key="id", value="3db4adj3d", 将返回一个空字符串。
何时使用。
可怕的 samesite 属性first-party cookie 和 third-party cookie查看
set-cookie: simplecookiename=c00l-c00k13; path=/first-party是指你登录或使用的网站所发行的 cookie,而third-party cookie 常为一些广告网站,有侵犯隐私以及安全隐患美国读金融研究生gre gmt。
我们将这类 cookie 称为 first-party美国读金融研究生gre gmt。也就是说,我在浏览器中访问该url,并且如果我访问相同的url或该站点的另一个路径(假设path为/),则浏览器会将cookie发送回该网站。
现在考虑在托管的远程资源中加载图像。
该远程资源又会自行设置一个cookie:
我们将这种 cookie 称为third-party(第三方) cookie美国读金融研究生gre gmt。
第三方 cookie 除了用于 csrf 攻击,还可以用于用户追踪美国读金融研究生gre gmt。比如,facebook 在第三方网站插入一张看不见的图片。
浏览器加载上面代码时,就会向 facebook 发出带有 cookie 的请求,从而 facebook 就会知道你是谁,访问了什么网站美国读金融研究生gre gmt。
使用 samesite 属性cookie 的samesite 属性用来限制third-party cookie,从而减少安全风险美国读金融研究生gre gmt。它可以设置三个值。
strictlaxnonestrict最为严格,完全禁止第三方 cookie,跨站点时,任何情况下都不会发送 cookie美国读金融研究生gre gmt。换言之,只有当前网页的 url 与请求目标一致,才会带上 cookie。
set-cookie: cookiename=cookievalue; samesite=strict;这个规则过于严格,可能造成非常不好的用户体验美国读金融研究生gre gmt。比如,当前网页有一个 github 链接,用户点击跳转就不会带有 github 的 cookie,跳转过去总是未登陆状态。
lax规则稍稍放宽,大多数情况也是不发送第三方 cookie,但是导航到目标网址的 get 请求除外美国读金融研究生gre gmt。
set-cookie: cookiename=cookievalue; samesite=lax;导航到目标网址的 get 请求,只包括三种情况:链接,预加载请求,get 表单美国读金融研究生gre gmt。详见下表。
设置了strict或lax以后,基本就杜绝了 csrf 攻击美国读金融研究生gre gmt。当然,前提是用户浏览器支持 samesite 属性。
chrome 计划将lax变为默认设置美国读金融研究生gre gmt。这时,网站可以选择显式关闭samesite属性,将其设为none。不过,前提是必须同时设置secure属性(cookie 只能通过 协议发送),否则无效。
下面的设置无效美国读金融研究生gre gmt。
set-cookie: widget_session=abc123; samesite=none下面的设置有效美国读金融研究生gre gmt。
set-cookie: widget_session=abc123; samesite=none; securecookies 和 认证身份验证是 web 开发中最具挑战性的任务之一美国读金融研究生gre gmt。关于这个主题似乎有很多困惑,因为jwt中的基于令牌的身份验证似乎要取代“旧的”、可靠的模式,如基于会话的身份验证。
来看看 cookie 在这里扮演什么角色美国读金融研究生gre gmt。
基于会话的身份验证身份验证是 cookie 最常见的用例之一美国读金融研究生gre gmt。
当你访问一个请求身份验证的网站时,后端将通过凭据提交(例如通过表单)在后台发送一个set-cookie标头到前端美国读金融研究生gre gmt。
型的会话 cookie 如下所示:
set-cookie: sessionid=sty1z3kz11mpqxjv648mqwlx4ginpt6c; expires=tue, 09 jun 2020 15:46:52 gmt; 。
这是浏览器可以清楚看到的唯一标识符美国读金融研究生gre gmt。每当通过身份验证的用户向后端请求新页面时,浏览器就会发回会话cookie。
基于会话的身份验证是有状态的,因为后端必须跟踪每个用户的会话美国读金融研究生gre gmt。这些会话的存储可能是:
数据库像 redis 这样的键/值存储文件系统在这三个会话存储中,redis 之类应优先于数据库或文件系统美国读金融研究生gre gmt。
请注意,基于会话的身份验证与浏览器的会话存储无关美国读金融研究生gre gmt。
之所以称为基于会话的会话,是因为用于用户识别的相关数据存在于后端的会话存储中,这与浏览器的会话存储不同美国读金融研究生gre gmt。
何时使用基于会话的身份验证只要能使用就使用它美国读金融研究生gre gmt。基于会话的身份验证是一种最简单、安全、直接的网站身份验证形式。默认情况下,它可以在django等所有流行的web框架上使用。
但是,它的状态特性也是它的主要缺点,特别是当网站是由负载均衡器提供服务时美国读金融研究生gre gmt。在这种情况下,像粘贴会话,或者在集中的redis存储上存储会话这样的技术会有所帮助。
关于 jwt 的说明jwt是 json web tokens的缩写,是一种身份验证机制,近年来越来越流行美国读金融研究生gre gmt。
jwt 非常适合单页和移动应用程序,但它带来了一系列新挑战美国读金融研究生gre gmt。想要针对api进行身份验证的前端应用程序的典型流程如下:
前端将凭证发送到后端后端检查凭证并发回令牌前端在每个后续请求上带上该令牌这种方法带来的主要问题是:为了使用户保持登录状态美国读金融研究生gre gmt,我将该令牌存储在前端的哪个地方?
对于前端开发来说,最自然的事情是将令牌保存在localstorage中美国读金融研究生gre gmt。由于许多原因,这很糟糕。
localstorage很容易从 js 代码访问,而且它很容易成为xss攻击的目标美国读金融研究生gre gmt。
为了解决此问题,大多数开发人员都将jwt令牌保存在cookie中,以为。
将 samesite 设置为 strict 就可以完全保护 jwt免受csrf攻击
设置为samesite = strict的新samesite属性还将保护你的“熟化” jwt免受csrf攻击美国读金融研究生gre gmt。但是,由于samesite = strict不会在跨域请求上发送cookie,因此,这也完全使jwt的用例无效。
那samesite=lax呢?此模式允许使用安全的。
实际上,将jwt标记存储在cookie或localstorage中都不是好主意美国读金融研究生gre gmt。
如果你确实要使用jwt而不是坚持使用基于会话的身份验证并扩展会话存储,则可能要使用带有刷新令牌的jwt来保持用户登录美国读金融研究生gre gmt。
总结自1994年以来,。
cookies是简单的文本字符串,但可以通过domain和path对其权限进行控制,具有secure的cookie,只能通过 。
但是,对于所有预期的用途,cookie都可能使用户暴露于攻击和漏洞之中美国读金融研究生gre gmt。
浏览器的供应商和internet工程任务组(internet engineering task force)年复一年地致力于提高cookie的安全性,最近的一步是samesite美国读金融研究生gre gmt。
那么美国读金融研究生gre gmt,什么才算是比较安全cookie?,如下几点:
仅使用 。
作者:valentinog 译者:前端小智 来源:valentinog
原文:
本文转载自网络于2022-02-17发表在研究生信息,如有疑问,请联系凯发k8国际官网。 凯发k8官网手机客户端的版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
本文链接:https://www.gokaigai.com/meiguo/bi-xu-zhi-dao-shi-yong-wan-zheng-de-http-cookie-zhi-nan/
上一篇
下一篇
发表评论